From 2456592fd6f419b01b080d315da04937c375fdf3 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Tue, 29 Jul 2025 16:59:19 +1000 Subject: [PATCH 01/25] WIP on style updates for iOS 26 - Clear cards with glass effect, with system background when expanded - Rounder corners - Bigger close button - Bigger title --- .../TGCardViewController.swift | 33 ++++++++-- .../TGCardViewController.xib | 63 ++++++++++++------- .../TGCardViewController/cards/TGCard.swift | 4 +- .../cards/TGCardStyle.swift | 20 +++++- .../style/TGCardStyleKit.swift | 24 +++++-- .../style/TGCornerView.swift | 8 ++- .../views/TGCardDefaultTitleView.swift | 16 +++++ .../views/TGCardDefaultTitleView.xib | 19 +++--- 8 files changed, 142 insertions(+), 45 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 27797eb..83eb00a 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -155,6 +155,7 @@ open class TGCardViewController: UIViewController { @IBOutlet weak var mapShadow: UIView! @IBOutlet weak var cardWrapperShadow: UIView! @IBOutlet public weak var cardWrapperContent: UIView! + @IBOutlet weak var cardWrapperEffectView: UIVisualEffectView! fileprivate weak var cardTransitionShadow: UIView? @IBOutlet weak var statusBarBlurView: UIVisualEffectView! @IBOutlet weak var topFloatingView: UIStackView! @@ -309,6 +310,13 @@ open class TGCardViewController: UIViewController { mapView.translatesAutoresizingMaskIntoConstraints = false mapViewController.didMove(toParent: self) + if #available(iOS 26.0, *) { + cardWrapperEffectView.effect = UIGlassEffect(style: .regular) + cardWrapperEffectView.cornerConfiguration = .corners(radius: 44) + } else { + cardWrapperEffectView.effect = nil + } + setupGestures() // Create the default buttons @@ -623,6 +631,14 @@ open class TGCardViewController: UIViewController { fileprivate func updateMapShadow(for position: TGCardPosition) { mapShadow.alpha = position == .extended ? Constants.mapShadowVisibleAlpha : 0 mapShadow.isUserInteractionEnabled = position == .extended + + if #available(iOS 26.0, *) { + let background: UIColor = position == .extended ? .systemBackground : .clear + topCardView?.grabHandle?.backgroundColor = background + topCardView?.titleView?.backgroundColor = background + cardWrapperContent.backgroundColor = background + cardWrapperContent.layer.cornerRadius = position == .extended ? 44 : 0 + } } private func toggleCardWrappers(hide: Bool, prepareOnly: Bool = false) { @@ -899,18 +915,18 @@ extension TGCardViewController { // already have such a shadow. if oldTop != nil, animated, cardTransitionShadow == nil, let cardView = cardView { - let shadow = TGCornerView(frame: cardWrapperContent.bounds) + let shadow = TGCornerView(frame: cardWrapperEffectView.bounds) shadow.frame.size.height += 50 // for bounciness shadow.backgroundColor = .black shadow.alpha = 0 - cardWrapperContent.insertSubview(shadow, belowSubview: cardView) + cardWrapperEffectView.contentView.insertSubview(shadow, belowSubview: cardWrapperContent) cardTransitionShadow = shadow } let cardAnimations = { self.toggleCardWrappers(hide: cardView == nil, prepareOnly: true) - guard let cardView = cardView else { return } + guard let cardView else { return } self.updateMapShadow(for: animateTo.position) cardView.frame = self.cardWrapperContent.bounds self.cardTransitionShadow?.alpha = 0.15 @@ -1069,10 +1085,10 @@ extension TGCardViewController { // We animate the view moving back down to the bottom // we also temporarily insert a shadow view again, if there's a card below if animated, newTop != nil, cardTransitionShadow == nil, let topView = topView { - let shadow = TGCornerView(frame: cardWrapperContent.bounds) + let shadow = TGCornerView(frame: cardWrapperEffectView.bounds) shadow.backgroundColor = .black shadow.alpha = 0.15 - cardWrapperContent.insertSubview(shadow, belowSubview: topView) + cardWrapperEffectView.contentView.insertSubview(shadow, belowSubview: cardWrapperContent) cardTransitionShadow = shadow } @@ -1874,7 +1890,12 @@ extension TGCardViewController { private func updateHeaderStyle() { @MainActor func applyCornerStyle(to view: UIView) { - let radius: CGFloat = 16 + let radius: CGFloat + if #available(iOS 26.0, *) { + radius = 44 + } else { + radius = 16 + } let roundAllCorners = cardIsNextToMap(in: traitCollection) view.layer.maskedCorners = roundAllCorners diff --git a/Sources/TGCardViewController/TGCardViewController.xib b/Sources/TGCardViewController/TGCardViewController.xib index 1f8b506..fa00b73 100644 --- a/Sources/TGCardViewController/TGCardViewController.xib +++ b/Sources/TGCardViewController/TGCardViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -17,6 +17,7 @@ + @@ -82,19 +83,19 @@ - + - + - + - + - + @@ -107,7 +108,7 @@ - + @@ -140,7 +141,7 @@ - + @@ -166,30 +167,46 @@ - + - - + + + + + + + + + + + + + + + + + + - + + - - - + + + - - + - + @@ -255,13 +272,13 @@ - + - + @@ -271,11 +288,11 @@ - + - + diff --git a/Sources/TGCardViewController/cards/TGCard.swift b/Sources/TGCardViewController/cards/TGCard.swift index b4a176b..a3c1913 100644 --- a/Sources/TGCardViewController/cards/TGCard.swift +++ b/Sources/TGCardViewController/cards/TGCard.swift @@ -127,7 +127,9 @@ open class TGCard: UIResponder, TGPreferrableView { } /// The position to display the card in, when pushing - public let initialPosition: TGCardPosition? + /// + /// Should only be modified until the card is first pushed. + public var initialPosition: TGCardPosition? /// Whether the close button should be visible on the card title /// diff --git a/Sources/TGCardViewController/cards/TGCardStyle.swift b/Sources/TGCardViewController/cards/TGCardStyle.swift index 645cca6..6ff5324 100644 --- a/Sources/TGCardViewController/cards/TGCardStyle.swift +++ b/Sources/TGCardViewController/cards/TGCardStyle.swift @@ -13,7 +13,17 @@ public struct TGCardStyle { public static let `default` = TGCardStyle() /// Font to use for title, defaults to bold system font with size 17pt. - public var titleFont: UIFont = .boldSystemFont(ofSize: 17) + public var titleFont: UIFont = { + if #available(iOS 26.0, *) { + if let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .largeTitle).withSymbolicTraits(.traitBold) { + return UIFont.init(descriptor: descriptor, size: descriptor.pointSize) + } else { + return .preferredFont(forTextStyle: .largeTitle) + } + } else { + return .boldSystemFont(ofSize: 17) + } + }() /// Title colour, defaults to system label color public var titleTextColor: UIColor = .label @@ -25,7 +35,13 @@ public struct TGCardStyle { public var subtitleTextColor: UIColor = .secondaryLabel /// Colour to use for the background, defaults to system background color - public var backgroundColor: UIColor = .systemBackground + public var backgroundColor: UIColor = { + if #available(iOS 26.0, *) { + return .clear + } else { + return .systemBackground + } + }() /// Colour to use for the grab handle on the card, defaults to system secondary label color public var grabHandleColor: UIColor = .secondaryLabel diff --git a/Sources/TGCardViewController/style/TGCardStyleKit.swift b/Sources/TGCardViewController/style/TGCardStyleKit.swift index 00ef421..6947a29 100644 --- a/Sources/TGCardViewController/style/TGCardStyleKit.swift +++ b/Sources/TGCardViewController/style/TGCardStyleKit.swift @@ -190,8 +190,16 @@ class TGCardStyleKit : NSObject { } @objc dynamic class func imageOfCardCloseIcon(closeButtonBackground: UIColor = UIColor(red: 0.130, green: 0.160, blue: 0.200, alpha: 0.080), closeButtonCross: UIColor = UIColor(red: 0.440, green: 0.460, blue: 0.480, alpha: 1.000)) -> UIImage { - UIGraphicsBeginImageContextWithOptions(CGSize(width: 24, height: 24), false, 0) - TGCardStyleKit.drawCardCloseIcon(closeButtonBackground: closeButtonBackground, closeButtonCross: closeButtonCross) + let width: CGFloat + if #available(iOS 26.0, *) { + width = 44 + } else { + width = 24 + } + + let frame = CGRect(origin: .init(x: 0, y: 0), size: CGSize(width: width, height: width)) + UIGraphicsBeginImageContextWithOptions(frame.size, false, 0) + TGCardStyleKit.drawCardCloseIcon(frame: frame, closeButtonBackground: closeButtonBackground, closeButtonCross: closeButtonCross) let imageOfCardCloseIcon = UIGraphicsGetImageFromCurrentImageContext()!.withRenderingMode(.alwaysOriginal) UIGraphicsEndImageContext() @@ -200,8 +208,16 @@ class TGCardStyleKit : NSObject { } @objc dynamic class func imageOfCardArrowIcon(closeButtonBackground: UIColor = UIColor(red: 0.130, green: 0.160, blue: 0.200, alpha: 0.080), closeButtonCross: UIColor = UIColor(red: 0.440, green: 0.460, blue: 0.480, alpha: 1.000), arrowRotation: CGFloat = 0) -> UIImage { - UIGraphicsBeginImageContextWithOptions(CGSize(width: 24, height: 24), false, 0) - TGCardStyleKit.drawCardArrowIcon(closeButtonBackground: closeButtonBackground, closeButtonCross: closeButtonCross, arrowRotation: arrowRotation) + let width: CGFloat + if #available(iOS 26.0, *) { + width = 44 + } else { + width = 24 + } + + let frame = CGRect(origin: .init(x: 0, y: 0), size: CGSize(width: width, height: width)) + UIGraphicsBeginImageContextWithOptions(frame.size, false, 0) + TGCardStyleKit.drawCardArrowIcon(frame: frame, closeButtonBackground: closeButtonBackground, closeButtonCross: closeButtonCross, arrowRotation: arrowRotation) let imageOfCardArrowIcon = UIGraphicsGetImageFromCurrentImageContext()!.withRenderingMode(.alwaysOriginal) UIGraphicsEndImageContext() diff --git a/Sources/TGCardViewController/style/TGCornerView.swift b/Sources/TGCardViewController/style/TGCornerView.swift index f55a957..bedeb99 100644 --- a/Sources/TGCardViewController/style/TGCornerView.swift +++ b/Sources/TGCardViewController/style/TGCornerView.swift @@ -17,9 +17,15 @@ public class TGCornerView: UIView { super.layoutSubviews() if Self.roundedCorners { + let radius: CGFloat + if #available(iOS 26.0, *) { + radius = 44 + } else { + radius = 16 + } let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], - cornerRadii: CGSize(width: 16, height: 16)) + cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.cgPath layer.mask = mask diff --git a/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift b/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift index 3f150af..1f13750 100644 --- a/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift +++ b/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift @@ -17,6 +17,10 @@ class TGCardDefaultTitleView: UIView, TGPreferrableView { @IBOutlet weak var dismissButton: UIButton! @IBOutlet weak var accessoryViewContainer: UIView! + @IBOutlet weak var topLevelTopConstraint: NSLayoutConstraint! + @IBOutlet weak var labelStackLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var innerTrailingConstraint: NSLayoutConstraint! + // By default, the top level stack snaps to all edges // of the default title view. The space to the bottom // edge is exposed, so that we can allow the accessory @@ -26,6 +30,18 @@ class TGCardDefaultTitleView: UIView, TGPreferrableView { override func awakeFromNib() { super.awakeFromNib() + if #available(iOS 26.0, *) { + topLevelTopConstraint.constant = 0 + labelStackLeadingConstraint.constant = 22 + innerTrailingConstraint.constant = 37 // 9 pixels extra space to the side + + titleLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 32).isActive = true + } else { + topLevelTopConstraint.constant = 8 + labelStackLeadingConstraint.constant = 16 + innerTrailingConstraint.constant = 28 + } + // Here we set the minimum width and height to provide sufficient hit // target. The priority is lowered because we may need to hide the // button and in such case, stack view will reduce its size to zero, diff --git a/Sources/TGCardViewController/views/TGCardDefaultTitleView.xib b/Sources/TGCardViewController/views/TGCardDefaultTitleView.xib index 178086c..2dd4b4e 100644 --- a/Sources/TGCardViewController/views/TGCardDefaultTitleView.xib +++ b/Sources/TGCardViewController/views/TGCardDefaultTitleView.xib @@ -1,9 +1,9 @@ - + - + @@ -17,19 +17,19 @@ - + - + - + - + @@ -76,11 +76,14 @@ + + + From d13e5e8994e141fd8686a488425b396d66de3974 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 31 Jul 2025 11:29:59 +1000 Subject: [PATCH 02/25] WIP on edge padding unless in extended position --- .../TGCardViewController.swift | 10 ++- .../TGCardViewController.xib | 63 ++++++++++--------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 83eb00a..50cbc9a 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -173,6 +173,8 @@ open class TGCardViewController: UIViewController { @IBOutlet weak var cardWrapperHeightConstraint: NSLayoutConstraint! @IBOutlet weak var cardWrapperDynamicLeadingConstraint: NSLayoutConstraint! @IBOutlet weak var cardWrapperStaticLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var cardWrapperDynamicTrailingConstraint: NSLayoutConstraint! + @IBOutlet weak var cardWrapperDynamicBottomConstraint: NSLayoutConstraint! // Positioning the header view @IBOutlet weak var headerViewHeightConstraint: NSLayoutConstraint! @@ -295,6 +297,8 @@ open class TGCardViewController: UIViewController { TGCornerView.roundedCorners = mode == .floating cardWrapperDynamicLeadingConstraint.isActive = mode == .floating cardWrapperStaticLeadingConstraint.isActive = mode == .sidebar + cardWrapperDynamicTrailingConstraint.isActive = mode == .floating + cardWrapperDynamicBottomConstraint.isActive = mode == .floating toggleCardWrappers(hide: true) sidebarSeparator.backgroundColor = .separator @@ -312,7 +316,7 @@ open class TGCardViewController: UIViewController { if #available(iOS 26.0, *) { cardWrapperEffectView.effect = UIGlassEffect(style: .regular) - cardWrapperEffectView.cornerConfiguration = .corners(radius: 44) + cardWrapperEffectView.cornerConfiguration = .corners(topLeftRadius: 44, topRightRadius: 44, bottomLeftRadius: .containerConcentric(minimum: 44), bottomRightRadius: .containerConcentric(minimum: 44)) } else { cardWrapperEffectView.effect = nil } @@ -638,6 +642,10 @@ open class TGCardViewController: UIViewController { topCardView?.titleView?.backgroundColor = background cardWrapperContent.backgroundColor = background cardWrapperContent.layer.cornerRadius = position == .extended ? 44 : 0 + + cardWrapperDynamicLeadingConstraint.constant = position == .extended ? 0 : 8 + cardWrapperDynamicTrailingConstraint.constant = position == .extended ? 0 : 8 + cardWrapperDynamicBottomConstraint.constant = position == .extended ? 0 : 8 } } diff --git a/Sources/TGCardViewController/TGCardViewController.xib b/Sources/TGCardViewController/TGCardViewController.xib index fa00b73..3cb4642 100644 --- a/Sources/TGCardViewController/TGCardViewController.xib +++ b/Sources/TGCardViewController/TGCardViewController.xib @@ -1,9 +1,9 @@ - - + + - + @@ -16,7 +16,9 @@ + + @@ -43,29 +45,29 @@ - + - + - + - + - + - + @@ -83,19 +85,19 @@ - + - + - + - + - + @@ -108,7 +110,7 @@ - + @@ -127,7 +129,7 @@ - + @@ -135,13 +137,13 @@ - + - + @@ -165,16 +167,16 @@ - + - + - + - + @@ -226,10 +228,9 @@ - - + @@ -239,10 +240,11 @@ - + + @@ -250,6 +252,7 @@ + @@ -274,10 +277,10 @@ + - @@ -291,15 +294,15 @@ - + - + - + From 9f3e411e28fba250446f99fc37475c86cef66af0 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 6 Aug 2025 13:37:48 +1000 Subject: [PATCH 03/25] Xcode 16 compile fix and warnings --- Sources/TGCardViewController/TGCardViewController.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 50cbc9a..17d9892 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -314,12 +314,17 @@ open class TGCardViewController: UIViewController { mapView.translatesAutoresizingMaskIntoConstraints = false mapViewController.didMove(toParent: self) +#if compiler(>=6.2) // Xcode 26 if #available(iOS 26.0, *) { cardWrapperEffectView.effect = UIGlassEffect(style: .regular) cardWrapperEffectView.cornerConfiguration = .corners(topLeftRadius: 44, topRightRadius: 44, bottomLeftRadius: .containerConcentric(minimum: 44), bottomRightRadius: .containerConcentric(minimum: 44)) + cardWrapperEffectView.clipsToBounds = true } else { cardWrapperEffectView.effect = nil } +#else + cardWrapperEffectView.effect = nil +#endif setupGestures() @@ -922,7 +927,7 @@ extension TGCardViewController { // old. Only do that if the previous transition completed, i.e., we didn't // already have such a shadow. - if oldTop != nil, animated, cardTransitionShadow == nil, let cardView = cardView { + if oldTop != nil, animated, cardTransitionShadow == nil { let shadow = TGCornerView(frame: cardWrapperEffectView.bounds) shadow.frame.size.height += 50 // for bounciness shadow.backgroundColor = .black @@ -1092,7 +1097,7 @@ extension TGCardViewController { // 5. Do the transition, optionally animated. // We animate the view moving back down to the bottom // we also temporarily insert a shadow view again, if there's a card below - if animated, newTop != nil, cardTransitionShadow == nil, let topView = topView { + if animated, newTop != nil, cardTransitionShadow == nil { let shadow = TGCornerView(frame: cardWrapperEffectView.bounds) shadow.backgroundColor = .black shadow.alpha = 0.15 From 9f9536e366d03a1439becb70375898514abbe876 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 6 Aug 2025 14:36:57 +1000 Subject: [PATCH 04/25] Fix for dragging by content on iOS 26 --- .../TGCardViewController/TGCardViewController.swift | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 17d9892..165fdcc 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -1496,6 +1496,10 @@ extension TGCardViewController { @objc fileprivate func handleInnerPan(_ recogniser: UIPanGestureRecognizer) { + if #available(iOS 26.0, *) { + return // Handled automatically. Woah. + } + guard mode == .floating, let scrollView = recogniser.view as? UIScrollView, @@ -2137,7 +2141,14 @@ extension TGCardViewController: UIGestureRecognizerDelegate { scrollView.isScrollEnabled = true } - return false + // iOS 26 and up automatically handles the dragging the outer card while + // we do the inner pan. So we can let it pass. This works in combination + // with the early exist in handleInnerPan. + if #available(iOS 26.0, *) { + return true + } else { + return false + } } } From 3900a4af1fd2077149913cc71aa61e578de08c90 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 6 Aug 2025 15:18:18 +1000 Subject: [PATCH 05/25] Update paddings, remove status bar blur on iOS 26 --- .../TGCardViewController.swift | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 165fdcc..d0d6aec 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -293,6 +293,10 @@ open class TGCardViewController: UIViewController { override open func viewDidLoad() { super.viewDidLoad() + if #available(iOS 26.0, *) { + statusBarBlurView.isHidden = true + } + // mode-specific styling TGCornerView.roundedCorners = mode == .floating cardWrapperDynamicLeadingConstraint.isActive = mode == .floating @@ -648,9 +652,15 @@ open class TGCardViewController: UIViewController { cardWrapperContent.backgroundColor = background cardWrapperContent.layer.cornerRadius = position == .extended ? 44 : 0 - cardWrapperDynamicLeadingConstraint.constant = position == .extended ? 0 : 8 - cardWrapperDynamicTrailingConstraint.constant = position == .extended ? 0 : 8 - cardWrapperDynamicBottomConstraint.constant = position == .extended ? 0 : 8 + let padding: CGFloat = switch position { + case .extended: 0 + case .peaking: 6 + case .collapsed: 22 + } + + cardWrapperDynamicLeadingConstraint.constant = padding + cardWrapperDynamicTrailingConstraint.constant = padding + cardWrapperDynamicBottomConstraint.constant = padding } } From b9c13e65317144e26325d40017587a9d7c8d6941 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 6 Aug 2025 15:37:38 +1000 Subject: [PATCH 06/25] Allow setting tracking colour, tweak button styles --- .../TGButtonPosition.swift | 8 ++++-- .../TGCardViewController.swift | 27 ++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Sources/TGCardViewController/TGButtonPosition.swift b/Sources/TGCardViewController/TGButtonPosition.swift index 3c12925..9599c0a 100644 --- a/Sources/TGCardViewController/TGButtonPosition.swift +++ b/Sources/TGCardViewController/TGButtonPosition.swift @@ -20,9 +20,10 @@ public enum TGButtonPosition { public struct TGButtonStyle { /// Default style is rounded rect, no special tint colour and translucent - public init(shape: TGButtonStyle.Shape = .roundedRect, tintColor: UIColor? = nil, isTranslucent: Bool = true) { + public init(shape: TGButtonStyle.Shape = .roundedRect, tintColor: UIColor? = nil, trackingColor: UIColor? = nil, isTranslucent: Bool = true) { self.shape = shape self.tintColor = tintColor + self.trackingColor = trackingColor self.isTranslucent = isTranslucent } @@ -42,6 +43,9 @@ public struct TGButtonStyle { /// Custom tint colour. Uses default tint colour if set to `nil` public let tintColor: UIColor? - + + /// Prominent colour to pass to tracking button. Uses default tint colour if set to `nil` + public let trackingColor: UIColor? + public let isTranslucent: Bool } diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index d0d6aec..42c7a71 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -323,6 +323,9 @@ open class TGCardViewController: UIViewController { cardWrapperEffectView.effect = UIGlassEffect(style: .regular) cardWrapperEffectView.cornerConfiguration = .corners(topLeftRadius: 44, topRightRadius: 44, bottomLeftRadius: .containerConcentric(minimum: 44), bottomRightRadius: .containerConcentric(minimum: 44)) cardWrapperEffectView.clipsToBounds = true + + // Map floating bar buttons don't need to be styled here, that's + // handled in `applyToolbarItemStyle` } else { cardWrapperEffectView.effect = nil } @@ -1778,12 +1781,18 @@ extension TGCardViewController { if let customTint = buttonStyle.tintColor { view.tintColor = customTint + } else { + view.tintColor = nil } guard let visualView = view as? UIVisualEffectView else { return assertionFailure() } - if buttonStyle.isTranslucent { + if #available(iOS 26.0, *) { + visualView.effect = UIGlassEffect(style: .regular) + visualView.layer.borderWidth = 0 + visualView.layer.shadowOpacity = 0 + } else if buttonStyle.isTranslucent { visualView.effect = UIBlurEffect(style: .regular) visualView.layer.borderWidth = 0 visualView.layer.shadowOpacity = 0 @@ -1800,6 +1809,22 @@ extension TGCardViewController { apply(on: topFloatingViewWrapper) apply(on: bottomFloatingViewWrapper) + + if showDefaultButtons, let defaultButtons, let customTint = buttonStyle.trackingColor { + for view in defaultButtons { + for subview in view.subviews { + if let tracker = subview as? MKUserTrackingButton { + tracker.tintColor = customTint + + // For some reason the MKUserTrackingButton's internal doesn't want + // to inherit the tint of the button. So we go in deep. + for internalView in tracker.subviews { + internalView.tintColor = customTint + } + } + } + } + } } public func updateMapToolbarItems() { From bd9a172be22e68892fef9a1edf2fdaba3c4d134b Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 6 Aug 2025 16:20:51 +1000 Subject: [PATCH 07/25] Fix leading padding getting stuck at 0 --- Sources/TGCardViewController/TGCardViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 42c7a71..ddc15c1 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -476,6 +476,7 @@ open class TGCardViewController: UIViewController { super.traitCollectionDidChange(previousTraitCollection) cardWrapperHeightConstraint.constant = extendedMinY * -1 + cardWrapperStaticLeadingConstraint.isActive = cardIsNextToMap(in: traitCollection) // When trait collection changes, try to keep the same card position if let previous = previousCardPosition { From 31c65234d5dabfa935bb113e29f2faf19bffe8f6 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 7 Aug 2025 11:43:20 +1000 Subject: [PATCH 08/25] Page header styling --- .../TGCardViewController.swift | 16 ++++++++++------ .../cards/TGPageHeaderView.swift | 9 +++++++++ .../cards/TGPageHeaderView.xib | 5 +++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index ddc15c1..c7b5ed2 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -1945,7 +1945,7 @@ extension TGCardViewController { func applyCornerStyle(to view: UIView) { let radius: CGFloat if #available(iOS 26.0, *) { - radius = 44 + radius = 22 } else { radius = 16 } @@ -1966,11 +1966,15 @@ extension TGCardViewController { updateStatusBar(headerIsVisible: isShowingHeader) - // same shadow as for card wrapper - headerView.layer.shadowColor = UIColor.black.cgColor - headerView.layer.shadowOffset = .zero - headerView.layer.shadowRadius = 12 - headerView.layer.shadowOpacity = 0.5 + if #available(iOS 26.0, *) { + // No header. Rely on this being a UIVisualEffectView + } else { + // same shadow as for card wrapper + headerView.layer.shadowColor = UIColor.black.cgColor + headerView.layer.shadowOffset = .zero + headerView.layer.shadowRadius = 12 + headerView.layer.shadowOpacity = 0.5 + } } private func updateHeaderConstraints() { diff --git a/Sources/TGCardViewController/cards/TGPageHeaderView.swift b/Sources/TGCardViewController/cards/TGPageHeaderView.swift index 87136c9..06755d5 100644 --- a/Sources/TGCardViewController/cards/TGPageHeaderView.swift +++ b/Sources/TGCardViewController/cards/TGPageHeaderView.swift @@ -13,6 +13,7 @@ public class TGPageHeaderView: TGHeaderView { @IBOutlet weak var accessoryWrapperView: UIView! @IBOutlet weak var accessoryWrapperHeightConstraint: NSLayoutConstraint! + @IBOutlet weak var accessoryLeadingConstraint: NSLayoutConstraint! @IBOutlet weak var accessoryTrailingConstraint: NSLayoutConstraint! @IBOutlet weak var buttonTrailingConstraint: NSLayoutConstraint! @@ -26,6 +27,14 @@ public class TGPageHeaderView: TGHeaderView { override public func awakeFromNib() { super.awakeFromNib() + if #available(iOS 26.0, *) { + accessoryLeadingConstraint.constant = 0 + accessoryTrailingConstraint.constant = 0 + } else { + accessoryLeadingConstraint.constant = 8 + accessoryTrailingConstraint.constant = 8 + } + rightButton?.isHidden = true accessoryWrapperView.isHidden = true preferredStatusBarStyle = .default diff --git a/Sources/TGCardViewController/cards/TGPageHeaderView.xib b/Sources/TGCardViewController/cards/TGPageHeaderView.xib index 0652e1d..bd64d45 100644 --- a/Sources/TGCardViewController/cards/TGPageHeaderView.xib +++ b/Sources/TGCardViewController/cards/TGPageHeaderView.xib @@ -1,9 +1,9 @@ - + - + @@ -45,6 +45,7 @@ + From 8e4ca6948b3f0d6c0ff40f54cf904f8acbcc26c1 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Fri, 22 Aug 2025 19:34:06 +1000 Subject: [PATCH 09/25] Proper fix for "drag content down to drag card down" handling on iOS 26 --- .../TGCardViewController.swift | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index c7b5ed2..ad2a16a 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -193,6 +193,8 @@ open class TGCardViewController: UIViewController { var mapViewController = TGMapViewController() public var mapView: UIView! { mapViewController.mapView } + private var initialScrollOffset: CGFloat = 0 + var panner: UIPanGestureRecognizer! var cardTapper: UITapGestureRecognizer! var mapShadowTapper: UITapGestureRecognizer! @@ -1507,24 +1509,32 @@ extension TGCardViewController { switchTo(.peaking, direction: .down, animated: true) } - + @objc fileprivate func handleInnerPan(_ recogniser: UIPanGestureRecognizer) { - if #available(iOS 26.0, *) { - return // Handled automatically. Woah. - } - guard mode == .floating, let scrollView = recogniser.view as? UIScrollView, scrollView == topCardView?.contentScrollView, panner.isEnabled, scrollView.refreshControl == nil - else { return } + else { + return + } - let negativity = scrollView.contentOffset.y + scrollView.contentInset.top + let negativity: CGFloat + if #available(iOS 26.0, *), scrollView.contentOffset.y <= 0 { + negativity = (recogniser.translation(in: cardWrapperContent).y - initialScrollOffset) * -1 + } else { + negativity = scrollView.contentOffset.y + scrollView.contentInset.top + } switch (negativity, recogniser.state) { + + + case (_, .began) : + self.initialScrollOffset = scrollView.contentOffset.y + case (0 ..< CGFloat.infinity, _): // Reset the transformation whenever we get back to positive offset scrollView.transform = .identity @@ -1568,9 +1578,11 @@ extension TGCardViewController { // the scroll view appear to stay in place (it's important to not // set the content offset to zero here!) self.mapViewController.additionalSafeAreaInsets = updateCardPosition(y: extendedMinY - negativity) - scrollView.transform = CGAffineTransform(translationX: 0, y: negativity) - scrollView.verticalScrollIndicatorInsets.top = scrollView.contentInset.top + negativity * -1 - + if #unavailable(iOS 26.0) { + scrollView.transform = CGAffineTransform(translationX: 0, y: negativity) + scrollView.verticalScrollIndicatorInsets.top = scrollView.contentInset.top + negativity * -1 + } + default: // Ignore other states such as began, failed, etc. break @@ -1790,7 +1802,9 @@ extension TGCardViewController { return assertionFailure() } if #available(iOS 26.0, *) { +#if compiler(>=6.2) // Xcode 26 proxy visualView.effect = UIGlassEffect(style: .regular) +#endif visualView.layer.borderWidth = 0 visualView.layer.shadowOpacity = 0 } else if buttonStyle.isTranslucent { @@ -2185,7 +2199,7 @@ extension TGCardViewController: UIGestureRecognizerDelegate { // we do the inner pan. So we can let it pass. This works in combination // with the early exist in handleInnerPan. if #available(iOS 26.0, *) { - return true + return scrollView.contentOffset.y <= 0 } else { return false } From 8d3c00f042e33fefef3ad6876ebfa1d040ab9897 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Mon, 25 Aug 2025 13:15:12 +1000 Subject: [PATCH 10/25] Better transition animations on iOS 26 --- .../TGCardViewController.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index ad2a16a..9cb8185 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -838,7 +838,7 @@ extension TGCardViewController { let cardView = top.buildCardView() cards.append( (top, animateTo.position, cardView) ) - if let cardView = cardView { + if let cardView { cardView.dismissButton?.addTarget(self, action: #selector(closeTapped(sender:)), for: .touchUpInside) let showClose = (delegate != nil || cards.count > 1) && top.showCloseButton cardView.updateDismissButton(show: showClose, isSpringLoaded: navigationButtonsAreSpringLoaded) @@ -859,6 +859,7 @@ extension TGCardViewController { // 4. Place the new view coming, preparing to animate in from the bottom cardView.frame = cardWrapperContent.bounds + cardView.alpha = 0 if animated { let offset = cardView.convert(.init(x: 0, y: mapViewWrapper.frame.maxY), to: cardWrapperShadow).y cardView.frame.origin.y = offset @@ -958,11 +959,12 @@ extension TGCardViewController { guard let cardView else { return } self.updateMapShadow(for: animateTo.position) cardView.frame = self.cardWrapperContent.bounds + cardView.alpha = 1 + oldTop?.view?.alpha = 0 self.cardTransitionShadow?.alpha = 0.15 } if self.mode != .floating { cardAnimations() - oldTop?.view?.alpha = 0 } // In some cases, the cardWrapperShadow frame might already have been @@ -994,7 +996,6 @@ extension TGCardViewController { completion: { _ in self.updateCardScrolling(allow: animateTo.position == .extended, view: cardView) self.previousCardPosition = animateTo.position - oldTop?.view?.alpha = 0 if notify { oldTop?.card.didDisappear(animated: animated) top.didAppear(animated: animated) @@ -1083,7 +1084,7 @@ extension TGCardViewController { } // 4. Determine and set new position of the card wrapper (relative to header!) - newTop?.view?.alpha = 1 + newTop?.view?.alpha = 0 // We only animate to the previous position if the card obscures the map updateCardStructure(card: newTop?.view, position: newTop?.lastPosition) @@ -1128,11 +1129,13 @@ extension TGCardViewController { topView?.frame.origin.y = self.cardWrapperContent.frame.maxY self.cardTransitionShadow?.alpha = 0 newTop?.view?.adjustContentAlpha(to: animateTo == .collapsed ? 0 : 1) + + newTop?.view?.alpha = 1 + topView?.alpha = 0 } if mode != .floating { cardAnimations() - topView?.alpha = 0 } UIView.animate( @@ -1158,7 +1161,6 @@ extension TGCardViewController { } // This line did crash in Adrian's simulator but only happens rarely; when?!? topView?.removeFromSuperview() - topView?.alpha = 1 self.cardTransitionShadow?.removeFromSuperview() self.updateForNewPosition(position: animateTo) self.updateResponderChainForNewTopCard() From 15660eb2bd8a168db12cdc10b2844a3353d4e583 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 4 Sep 2025 16:17:28 +1000 Subject: [PATCH 11/25] Fix for page card dragging and paging on iOS 26 --- .../TGCardViewController/TGCardViewController.swift | 12 +++++++++++- .../TGCardViewController/cards/TGPageCardView.xib | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 9cb8185..fc086c6 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -667,6 +667,7 @@ open class TGCardViewController: UIViewController { cardWrapperDynamicLeadingConstraint.constant = padding cardWrapperDynamicTrailingConstraint.constant = padding cardWrapperDynamicBottomConstraint.constant = padding + view.setNeedsUpdateConstraints() } } @@ -2148,7 +2149,16 @@ extension TGCardViewController: UIGestureRecognizerDelegate { } else if let pager = (topCardView as? TGPageCardView)?.pager, other == pager.panGestureRecognizer { // When our panner fires, block panning of the page card - return false + if #available(iOS 26.0, *) { + // iOS 26: Allow vertical card dragging when swiping vertically, + // but block it during horizontal swipes to enable clean paging + let velocity = panner.velocity(in: cardWrapperContent) + let swipeHorizontally = abs(velocity.x) > abs(velocity.y) + return !swipeHorizontally + + } else { + return false + } } else { // We don't want to interfere with any existing horizontal swipes, e.g., swipe to delete diff --git a/Sources/TGCardViewController/cards/TGPageCardView.xib b/Sources/TGCardViewController/cards/TGPageCardView.xib index 4064fb3..db0330b 100644 --- a/Sources/TGCardViewController/cards/TGPageCardView.xib +++ b/Sources/TGCardViewController/cards/TGPageCardView.xib @@ -1,9 +1,9 @@ - + - + @@ -13,7 +13,7 @@ - + From b1ebd4148a7e32065e925bd4937d54c405b5060a Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 4 Sep 2025 16:16:45 +1000 Subject: [PATCH 12/25] Fix bad use of x vs y --- Sources/TGCardViewController/cards/TGPageCardView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/TGCardViewController/cards/TGPageCardView.swift b/Sources/TGCardViewController/cards/TGPageCardView.swift index 4104de6..0367bce 100644 --- a/Sources/TGCardViewController/cards/TGPageCardView.swift +++ b/Sources/TGCardViewController/cards/TGPageCardView.swift @@ -357,7 +357,7 @@ extension TGPageCardView: UIScrollViewDelegate { visiblePageLogical = logical delegate?.didChangeCurrentPage(to: logical, animated: true) - lastHorizontalOffset = scrollView.contentOffset.y + lastHorizontalOffset = scrollView.contentOffset.x let topMost = cardView(index: logical) self.accessibilityElements = [topMost].compactMap { $0 } From d5aa41e798317ab6e5ca5fe546e58291bf31efbe Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 4 Sep 2025 16:43:27 +1000 Subject: [PATCH 13/25] Force hide separator if card is in collapsed mode --- .../TGCardViewController/TGCardViewController.swift | 5 +++++ Sources/TGCardViewController/cards/TGCardView.swift | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index fc086c6..c3fdccd 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -528,6 +528,7 @@ open class TGCardViewController: UIViewController { statusBarBlurHeightConstraint.constant = topOverlap topCardView?.adjustContentAlpha(to: cardPosition == .collapsed ? 0 : 1) + topCardView?.setSeparatorVisibility(forceHidden: cardPosition == .collapsed) updateFloatingViewsConstraints() updateTopInfoViewConstraints() view.setNeedsUpdateConstraints() @@ -850,6 +851,7 @@ extension TGCardViewController { // which is an additional 34px on iPhone X, we will see part of the card content // coming through. cardView.adjustContentAlpha(to: animateTo.position == .collapsed ? 0 : 1) + cardView.setSeparatorVisibility(forceHidden: animateTo.position == .collapsed) // This allows us to continuously pull down the card view while its // content is scrolled to the top. Note this only applies when the @@ -1130,6 +1132,7 @@ extension TGCardViewController { topView?.frame.origin.y = self.cardWrapperContent.frame.maxY self.cardTransitionShadow?.alpha = 0 newTop?.view?.adjustContentAlpha(to: animateTo == .collapsed ? 0 : 1) + newTop?.view?.setSeparatorVisibility(forceHidden: animateTo == .collapsed) newTop?.view?.alpha = 1 topView?.alpha = 0 @@ -1407,6 +1410,7 @@ extension TGCardViewController { animations: { self.updateMapShadow(for: snapTo.position) self.topCardView?.adjustContentAlpha(to: snapTo.position == .collapsed ? 0 : 1) + self.topCardView?.setSeparatorVisibility(forceHidden: snapTo.position == .collapsed) self.updateFloatingViewsVisibility(for: snapTo.position) self.view.layoutIfNeeded() self.mapViewController.additionalSafeAreaInsets = mapInset @@ -1630,6 +1634,7 @@ extension TGCardViewController { animations: { self.updateMapShadow(for: animateTo.position) self.topCardView?.adjustContentAlpha(to: animateTo.position == .collapsed ? 0 : 1) + self.topCardView?.setSeparatorVisibility(forceHidden: animateTo.position == .collapsed) self.updateFloatingViewsVisibility(for: animateTo.position) self.view.layoutIfNeeded() self.mapViewController.additionalSafeAreaInsets = mapInsets diff --git a/Sources/TGCardViewController/cards/TGCardView.swift b/Sources/TGCardViewController/cards/TGCardView.swift index adb1a3d..21e97ed 100644 --- a/Sources/TGCardViewController/cards/TGCardView.swift +++ b/Sources/TGCardViewController/cards/TGCardView.swift @@ -242,9 +242,20 @@ public class TGCardView: TGCornerView, TGPreferrableView { // MARK: - Content view configuration + private var forceHideSeparator = false + + func setSeparatorVisibility(forceHidden: Bool) { + forceHideSeparator = forceHidden + // Trigger separator update with current scroll state + if let contentScrollView = contentScrollView { + let actualOffset = contentScrollView.transform.ty < 0 ? 0 : contentScrollView.contentOffset.y + showSeparator(actualOffset > 0, offset: actualOffset) + } + } + func showSeparator(_ show: Bool, offset: CGFloat) { if let owningCard, owningCard.shouldToggleSeparator(show: show, offset: offset) { - contentSeparator?.isHidden = !show + contentSeparator?.isHidden = forceHideSeparator ? true : !show } else if let owningCard, owningCard.title.isExtended, owningCard.autoIgnoreContentInset, let contentScrollView, contentScrollView.isDecelerating, offset < 0 { // This handles the case where you fling the content down further than the From 41e48bccede741bfe362f224a7485afc1795445d Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 4 Sep 2025 17:12:20 +1000 Subject: [PATCH 14/25] Maintain iOS 26 padding across backgrounding/foregrounding --- .../TGCardViewController.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index c3fdccd..f9012c3 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -478,7 +478,22 @@ open class TGCardViewController: UIViewController { super.traitCollectionDidChange(previousTraitCollection) cardWrapperHeightConstraint.constant = extendedMinY * -1 + + // 1. Deactivate potentially conflicting constraints first + cardWrapperStaticLeadingConstraint.isActive = false + cardWrapperDynamicLeadingConstraint.isActive = false + cardWrapperDynamicTrailingConstraint.isActive = false + + // 2. Restore iOS 26 dynamic padding after trait collection changes (rotation/backgrounding) + updateMapShadow(for: cardPosition) + + // 3. Reactivate the correct constraints based on mode and layout cardWrapperStaticLeadingConstraint.isActive = cardIsNextToMap(in: traitCollection) + cardWrapperDynamicLeadingConstraint.isActive = mode == .floating + cardWrapperDynamicTrailingConstraint.isActive = mode == .floating + + // 4. Force layout with consistent state + view.layoutIfNeeded() // When trait collection changes, try to keep the same card position if let previous = previousCardPosition { From db03df8992fbb91323b7729f3953c601a8a0839b Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Fri, 5 Sep 2025 17:17:08 +1000 Subject: [PATCH 15/25] Fix dragging regression for pre-iOS 26 paging cards --- Sources/TGCardViewController/TGCardViewController.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index f9012c3..41410b9 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -303,8 +303,13 @@ open class TGCardViewController: UIViewController { TGCornerView.roundedCorners = mode == .floating cardWrapperDynamicLeadingConstraint.isActive = mode == .floating cardWrapperStaticLeadingConstraint.isActive = mode == .sidebar - cardWrapperDynamicTrailingConstraint.isActive = mode == .floating - cardWrapperDynamicBottomConstraint.isActive = mode == .floating + if #available(iOS 26.0, *) { + cardWrapperDynamicTrailingConstraint.isActive = mode == .floating + cardWrapperDynamicBottomConstraint.isActive = mode == .floating + } else { + cardWrapperDynamicTrailingConstraint.isActive = true + cardWrapperDynamicBottomConstraint.isActive = false + } toggleCardWrappers(hide: true) sidebarSeparator.backgroundColor = .separator From 955806368b97dd1c8332a4f51ce646997c04c845 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Tue, 9 Sep 2025 16:55:52 +1000 Subject: [PATCH 16/25] Fix sizing of hosting card's content, and add proper `didBuild` methods --- .../cards/TGHostingCard.swift | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Sources/TGCardViewController/cards/TGHostingCard.swift b/Sources/TGCardViewController/cards/TGHostingCard.swift index a4b970f..4e4b194 100644 --- a/Sources/TGCardViewController/cards/TGHostingCard.swift +++ b/Sources/TGCardViewController/cards/TGHostingCard.swift @@ -27,10 +27,17 @@ open class TGHostingCard: TGCard where Content: View { super.init(title: title, mapManager: mapManager, initialPosition: mapManager != nil ? initialPosition : .extended) } + open func didBuild(scrollView: UIScrollView) { + } + + open func didBuild(scrollView: UIScrollView, cardView: TGCardView) { + } + // MARK: - Constructing views open override func buildCardView() -> TGCardView? { let view = TGScrollCardView.instantiate(extended: title.isExtended) + view.translatesAutoresizingMaskIntoConstraints = false host.beginAppearanceTransition(true, animated: false) @@ -47,18 +54,30 @@ open class TGHostingCard: TGCard where Content: View { view.configure(scroller, with: self) host.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true - host.endAppearanceTransition() return view } + override public final func didBuild(cardView: TGCardView?, headerView: TGHeaderView?) { + + defer { super.didBuild(cardView: cardView, headerView: headerView) } + + guard let cardView, let scrollView = (cardView as? TGScrollCardView)?.embeddedScrollView else { + preconditionFailure() + } + + didBuild(scrollView: scrollView) + didBuild(scrollView: scrollView, cardView: cardView) + } + } @available(iOS 13.0, *) fileprivate class TGHostingController: UIHostingController where Content: View { - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + if let scroller = view.superview as? UIScrollView { let size = sizeThatFits(in: scroller.bounds.size) scroller.contentSize = size From f88bcacd786cee7fe33bbac9836021d3d329234f Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 10 Sep 2025 14:28:29 +1000 Subject: [PATCH 17/25] Fix iPad regression, making sure card stays next to map And use smaller corner radii --- .../TGCardViewController.swift | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/Sources/TGCardViewController/TGCardViewController.swift b/Sources/TGCardViewController/TGCardViewController.swift index 41410b9..314a032 100644 --- a/Sources/TGCardViewController/TGCardViewController.swift +++ b/Sources/TGCardViewController/TGCardViewController.swift @@ -298,16 +298,16 @@ open class TGCardViewController: UIViewController { if #available(iOS 26.0, *) { statusBarBlurView.isHidden = true } + let cardIsNextToMap = self.cardIsNextToMap(in: traitCollection) // mode-specific styling TGCornerView.roundedCorners = mode == .floating cardWrapperDynamicLeadingConstraint.isActive = mode == .floating cardWrapperStaticLeadingConstraint.isActive = mode == .sidebar + cardWrapperDynamicTrailingConstraint.isActive = mode == .floating && !cardIsNextToMap if #available(iOS 26.0, *) { - cardWrapperDynamicTrailingConstraint.isActive = mode == .floating cardWrapperDynamicBottomConstraint.isActive = mode == .floating } else { - cardWrapperDynamicTrailingConstraint.isActive = true cardWrapperDynamicBottomConstraint.isActive = false } toggleCardWrappers(hide: true) @@ -328,7 +328,16 @@ open class TGCardViewController: UIViewController { #if compiler(>=6.2) // Xcode 26 if #available(iOS 26.0, *) { cardWrapperEffectView.effect = UIGlassEffect(style: .regular) - cardWrapperEffectView.cornerConfiguration = .corners(topLeftRadius: 44, topRightRadius: 44, bottomLeftRadius: .containerConcentric(minimum: 44), bottomRightRadius: .containerConcentric(minimum: 44)) + if cardIsNextToMap { + cardWrapperEffectView.cornerConfiguration = .corners(radius: 12) + } else { + cardWrapperEffectView.cornerConfiguration = .corners( + topLeftRadius: 44, + topRightRadius: 44, + bottomLeftRadius: .containerConcentric(minimum: 44), + bottomRightRadius: .containerConcentric(minimum: 44) + ) + } cardWrapperEffectView.clipsToBounds = true // Map floating bar buttons don't need to be styled here, that's @@ -484,6 +493,20 @@ open class TGCardViewController: UIViewController { cardWrapperHeightConstraint.constant = extendedMinY * -1 + let cardIsNextToMap = cardIsNextToMap(in: traitCollection) + if #available(iOS 26.0, *) { + if cardIsNextToMap { + cardWrapperEffectView.cornerConfiguration = .corners(radius: 12) + } else { + cardWrapperEffectView.cornerConfiguration = .corners( + topLeftRadius: 44, + topRightRadius: 44, + bottomLeftRadius: .containerConcentric(minimum: 44), + bottomRightRadius: .containerConcentric(minimum: 44) + ) + } + } + // 1. Deactivate potentially conflicting constraints first cardWrapperStaticLeadingConstraint.isActive = false cardWrapperDynamicLeadingConstraint.isActive = false @@ -493,9 +516,9 @@ open class TGCardViewController: UIViewController { updateMapShadow(for: cardPosition) // 3. Reactivate the correct constraints based on mode and layout - cardWrapperStaticLeadingConstraint.isActive = cardIsNextToMap(in: traitCollection) + cardWrapperStaticLeadingConstraint.isActive = mode == .sidebar cardWrapperDynamicLeadingConstraint.isActive = mode == .floating - cardWrapperDynamicTrailingConstraint.isActive = mode == .floating + cardWrapperDynamicTrailingConstraint.isActive = mode == .floating && !cardIsNextToMap // 4. Force layout with consistent state view.layoutIfNeeded() @@ -677,12 +700,13 @@ open class TGCardViewController: UIViewController { topCardView?.grabHandle?.backgroundColor = background topCardView?.titleView?.backgroundColor = background cardWrapperContent.backgroundColor = background - cardWrapperContent.layer.cornerRadius = position == .extended ? 44 : 0 - let padding: CGFloat = switch position { - case .extended: 0 - case .peaking: 6 - case .collapsed: 22 + let cardIsNextToMap = cardIsNextToMap(in: traitCollection) + let padding: CGFloat = switch (position, cardIsNextToMap) { + case (_, true): 12 + case (.extended, _): 0 + case (.peaking, _): 6 + case (.collapsed, _): 22 } cardWrapperDynamicLeadingConstraint.constant = padding From 6c40b580a517fdbc729d669464bf87c56ed9f72b Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 17 Sep 2025 15:09:30 +1000 Subject: [PATCH 18/25] Fixes for TGHostingView's content size --- .../cards/TGHostingCard.swift | 35 ++++++------------- .../cards/TGScrollHostingCard.swift | 0 2 files changed, 10 insertions(+), 25 deletions(-) create mode 100644 Sources/TGCardViewController/cards/TGScrollHostingCard.swift diff --git a/Sources/TGCardViewController/cards/TGHostingCard.swift b/Sources/TGCardViewController/cards/TGHostingCard.swift index 4e4b194..68c4dee 100644 --- a/Sources/TGCardViewController/cards/TGHostingCard.swift +++ b/Sources/TGCardViewController/cards/TGHostingCard.swift @@ -22,7 +22,7 @@ open class TGHostingCard: TGCard where Content: View { mapManager: TGCompatibleMapManager? = nil, initialPosition: TGCardPosition? = nil) { - self.host = TGHostingController(rootView: rootView) + self.host = UIHostingController(rootView: rootView) super.init(title: title, mapManager: mapManager, initialPosition: mapManager != nil ? initialPosition : .extended) } @@ -37,24 +37,23 @@ open class TGHostingCard: TGCard where Content: View { open override func buildCardView() -> TGCardView? { let view = TGScrollCardView.instantiate(extended: title.isExtended) - view.translatesAutoresizingMaskIntoConstraints = false - - host.beginAppearanceTransition(true, animated: false) let scroller = UIScrollView(frame: .zero) + view.configure(scroller, with: self) + host.beginAppearanceTransition(true, animated: false) host.view.translatesAutoresizingMaskIntoConstraints = false scroller.addSubview(host.view) + NSLayoutConstraint.activate([ - host.view.leadingAnchor.constraint(equalTo: scroller.leadingAnchor), - host.view.topAnchor.constraint(equalTo: scroller.topAnchor), - host.view.trailingAnchor.constraint(equalTo: scroller.trailingAnchor), + host.view.leadingAnchor.constraint(equalTo: scroller.contentLayoutGuide.leadingAnchor), + host.view.topAnchor.constraint(equalTo: scroller.contentLayoutGuide.topAnchor), + host.view.trailingAnchor.constraint(equalTo: scroller.contentLayoutGuide.trailingAnchor), + host.view.bottomAnchor.constraint(equalTo: scroller.contentLayoutGuide.bottomAnchor), + host.view.widthAnchor.constraint(equalTo: scroller.frameLayoutGuide.widthAnchor), ]) - - view.configure(scroller, with: self) - - host.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true host.endAppearanceTransition() + return view } @@ -71,17 +70,3 @@ open class TGHostingCard: TGCard where Content: View { } } - -@available(iOS 13.0, *) -fileprivate class TGHostingController: UIHostingController where Content: View { - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - if let scroller = view.superview as? UIScrollView { - let size = sizeThatFits(in: scroller.bounds.size) - scroller.contentSize = size - view.heightAnchor.constraint(equalToConstant: size.height).isActive = true - } - } -} diff --git a/Sources/TGCardViewController/cards/TGScrollHostingCard.swift b/Sources/TGCardViewController/cards/TGScrollHostingCard.swift new file mode 100644 index 0000000..e69de29 From 8ff2494706fcab48c7569f704f826cfdd6577b0c Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Wed, 17 Sep 2025 17:38:14 +1000 Subject: [PATCH 19/25] Fix invalid size of UIHostingController's content By explicitly telling it to resize when its content resizes --- .../cards/TGHostingCard.swift | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/Sources/TGCardViewController/cards/TGHostingCard.swift b/Sources/TGCardViewController/cards/TGHostingCard.swift index 68c4dee..07bfa16 100644 --- a/Sources/TGCardViewController/cards/TGHostingCard.swift +++ b/Sources/TGCardViewController/cards/TGHostingCard.swift @@ -1,10 +1,11 @@ // // TGHostingCard.swift -// +// // // Created by Adrian Schönig on 21/4/21. // + import SwiftUI /// A hosting card can be used to use a SwiftUI `View` as the card's content. @@ -15,16 +16,31 @@ import SwiftUI @available(iOS 13.0, *) open class TGHostingCard: TGCard where Content: View { - private let host: UIHostingController + private let host: UIHostingController + private let relay: _TGSizeRelay public init(title: CardTitle, rootView: Content, mapManager: TGCompatibleMapManager? = nil, initialPosition: TGCardPosition? = nil) { - self.host = UIHostingController(rootView: rootView) - + let relay = _TGSizeRelay() + let observedRoot = rootView._tgOnSizeChange { [weak relay] in + relay?.onSize?($0) + } + self.host = UIHostingController(rootView: AnyView(observedRoot)) + self.relay = relay + super.init(title: title, mapManager: mapManager, initialPosition: mapManager != nil ? initialPosition : .extended) + + // After init, connect size changes to intrinsic invalidation so Auto Layout + // updates content height. UIHostingController doesn't manage to reliably + // do that itself, but nudging it this way does the trick. + relay.onSize = { [weak host = self.host] size in + guard let view = host?.view else { return } + view.invalidateIntrinsicContentSize() + view.setNeedsLayout() + } } open func didBuild(scrollView: UIScrollView) { @@ -70,3 +86,38 @@ open class TGHostingCard: TGCard where Content: View { } } + + +// MARK: - SwiftUI size reporting helper + +private struct _TGSizeKey: PreferenceKey { + static var defaultValue: CGSize = .zero + static func reduce(value: inout CGSize, nextValue: () -> CGSize) { + value = nextValue() + } +} + +private struct _TGSizeReader: ViewModifier { + let onChange: (CGSize) -> Void + func body(content: Content) -> some View { + content + .background( + GeometryReader { proxy in + Color.clear + .preference(key: _TGSizeKey.self, value: proxy.size) + .onPreferenceChange(_TGSizeKey.self, perform: onChange) + } + ) + } +} + +private extension View { + func _tgOnSizeChange(_ perform: @escaping (CGSize) -> Void) -> some View { + modifier(_TGSizeReader(onChange: perform)) + } +} + +private final class _TGSizeRelay { + var onSize: ((CGSize) -> Void)? +} + From 39edd20b46ecfc4687f4c138ae26ff1f6f01053f Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Mon, 29 Sep 2025 11:47:10 +1000 Subject: [PATCH 20/25] Make TGPlainCardView also work with other plain cards, not just TGPlainCard --- .../cards/TGPlainCard.swift | 2 +- .../cards/TGPlainCardView.swift | 21 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Sources/TGCardViewController/cards/TGPlainCard.swift b/Sources/TGCardViewController/cards/TGPlainCard.swift index 91f4634..7307728 100644 --- a/Sources/TGCardViewController/cards/TGPlainCard.swift +++ b/Sources/TGCardViewController/cards/TGPlainCard.swift @@ -58,7 +58,7 @@ open class TGPlainCard: TGCard { open override func buildCardView() -> TGCardView? { let view = TGPlainCardView.instantiate(extended: title.isExtended) - view.configure(with: self) + view.configure(with: self, contentView: contentView) return view } diff --git a/Sources/TGCardViewController/cards/TGPlainCardView.swift b/Sources/TGCardViewController/cards/TGPlainCardView.swift index bb021ea..de4bc6a 100644 --- a/Sources/TGCardViewController/cards/TGPlainCardView.swift +++ b/Sources/TGCardViewController/cards/TGPlainCardView.swift @@ -25,12 +25,8 @@ class TGPlainCardView: TGCardView { // MARK: - Configuration - override func configure(with card: TGCard) { - guard let plainCard = card as? TGPlainCard else { - preconditionFailure() - } - - super.configure(with: plainCard) + func configure(with card: TGCard, contentView: UIView?) { + super.configure(with: card) // build the header var adjustment: CGFloat = 1.0 // accounted for the separator @@ -48,15 +44,14 @@ class TGPlainCardView: TGCardView { contentViewHeightEqualToSuperviewHeightConstraint.constant = -1*adjustment } - // build the main content - if let content = plainCard.contentView { + if let content = contentView { content.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(content) - content.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true - content.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true - contentView.trailingAnchor.constraint(equalTo: content.trailingAnchor).isActive = true - contentView.bottomAnchor.constraint(equalTo: content.bottomAnchor).isActive = true + self.contentView.addSubview(content) + content.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true + content.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true + self.contentView.trailingAnchor.constraint(equalTo: content.trailingAnchor).isActive = true + self.contentView.bottomAnchor.constraint(equalTo: content.bottomAnchor).isActive = true } } From 72c8c6604b77d93add839a3d6e9e3424f799db04 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Mon, 29 Sep 2025 11:56:59 +1000 Subject: [PATCH 21/25] Remove host view's default background colours --- Sources/TGCardViewController/cards/TGHostingCard.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/TGCardViewController/cards/TGHostingCard.swift b/Sources/TGCardViewController/cards/TGHostingCard.swift index 07bfa16..541a460 100644 --- a/Sources/TGCardViewController/cards/TGHostingCard.swift +++ b/Sources/TGCardViewController/cards/TGHostingCard.swift @@ -59,6 +59,7 @@ open class TGHostingCard: TGCard where Content: View { host.beginAppearanceTransition(true, animated: false) host.view.translatesAutoresizingMaskIntoConstraints = false + host.view.backgroundColor = .clear scroller.addSubview(host.view) NSLayoutConstraint.activate([ From af683e660df7784df7e92081f12a6cebc2123446 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Mon, 29 Sep 2025 12:36:17 +1000 Subject: [PATCH 22/25] New helper for configuring close button --- .../TGCardViewController/cards/TGCard.swift | 31 +++++++++++++++++++ .../views/TGCardDefaultTitleView.swift | 7 +---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/Sources/TGCardViewController/cards/TGCard.swift b/Sources/TGCardViewController/cards/TGCard.swift index a3c1913..8eae12e 100644 --- a/Sources/TGCardViewController/cards/TGCard.swift +++ b/Sources/TGCardViewController/cards/TGCard.swift @@ -58,10 +58,12 @@ open class TGCard: UIResponder, TGPreferrableView { } /// The default image for the close button on a card, with default color + @available(*, deprecated, message: "Use `configureCloseButton` instead.") public static let closeButtonImage = TGCardStyleKit.imageOfCardCloseIcon() /// The default image for the close button on a card, with custom background /// color + @available(*, deprecated, message: "Use `configureCloseButton` instead.") public static func closeButtonImage(background: UIColor) -> UIImage { TGCardStyleKit.imageOfCardCloseIcon(closeButtonBackground: background) } @@ -72,6 +74,7 @@ open class TGCard: UIResponder, TGPreferrableView { /// /// - Parameter style: The style to use /// - Returns: A styled icon for use in a close button on a card + @available(*, deprecated, message: "Use `configureCloseButton` instead.") public static func closeButtonImage(style: TGCardStyle) -> UIImage { TGCardStyleKit.imageOfCardCloseIcon( closeButtonBackground: style.closeButtonBackgroundColor, @@ -79,6 +82,34 @@ open class TGCard: UIResponder, TGPreferrableView { ) } + public static func configureCloseButton(_ button: UIButton, style: TGCardStyle = .default) { + if #available(iOS 26.0, *) { + for state: UIControl.State in [.normal, .highlighted, .selected, .disabled, .focused] { + button.setTitle(nil, for: state) + } + + var config = UIButton.Configuration.glass() + config.title = nil + config.image = UIImage(systemName: "xmark") + config.imagePlacement = .all + config.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(pointSize: 22, weight: .medium) + config.imagePadding = 0 + config.contentInsets = .init(top: 10, leading: 10, bottom: 10, trailing: 10) + config.cornerStyle = .capsule + + button.configuration = config + + } else { + let image = TGCardStyleKit.imageOfCardCloseIcon( + closeButtonBackground: style.closeButtonBackgroundColor, + closeButtonCross: style.closeButtonCrossColor + ) + + button.setImage(image, for: .normal) + button.setTitle(nil, for: .normal) + } + } + /// A default image for an arrow pointing up or down, similar to the close button image public static func arrowButtonImage(direction: TGArrowDirection, background: UIColor, arrow: UIColor) -> UIImage { switch direction { diff --git a/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift b/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift index 1f13750..90d2262 100644 --- a/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift +++ b/Sources/TGCardViewController/views/TGCardDefaultTitleView.swift @@ -132,12 +132,7 @@ class TGCardDefaultTitleView: UIView, TGPreferrableView { if isInitial { dismissButton.isHidden = false - let closeButtonImage = TGCardStyleKit.imageOfCardCloseIcon( - closeButtonBackground: style.closeButtonBackgroundColor, - closeButtonCross: style.closeButtonCrossColor - ) - dismissButton.setImage(closeButtonImage, for: .normal) - dismissButton.setTitle(nil, for: .normal) + TGCard.configureCloseButton(dismissButton, style: style) } } From 26f10dd715e19d3728eb6c23f214c84ba9a8e57e Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 9 Oct 2025 14:07:03 +1100 Subject: [PATCH 23/25] Bump macOS and Xcode versions to Tahoe/Sequoia --- .github/workflows/swift.yml | 56 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 1cf5463..a4eb126 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -2,41 +2,41 @@ name: Swift on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] jobs: - build_xcode_sonoma: - runs-on: macos-14 + build_xcode_tahoe: + runs-on: macos-26 steps: - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: 15.3 # latest-stable - - uses: actions/checkout@v4 - - name: Build TGCardVC - run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - uses: actions/checkout@v4 + - name: Build TGCardVC + run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' - build_xcode_ventura: - runs-on: macos-13 + build_xcode_sequoia: + runs-on: macos-15 steps: - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - uses: actions/checkout@v4 - - name: Build TGCardVC - run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' - + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - uses: actions/checkout@v4 + - name: Build TGCardVC + run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' + examples: - runs-on: macos-14 + runs-on: macos-15 steps: - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: 15.3 # latest-stable - - uses: actions/checkout@v4 - - name: Build Example - run: | - cd Example - xcodebuild build -scheme 'Example' -destination 'platform=iOS Simulator,name=iPhone 14' + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - uses: actions/checkout@v4 + - name: Build Example + run: | + cd Example + xcodebuild build -scheme 'Example' -destination 'platform=iOS Simulator,name=iPhone 14' From 1f07c63daa1697a07e8b0de6cd2bb06c957104c9 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 9 Oct 2025 14:10:37 +1100 Subject: [PATCH 24/25] Generic names for GHAs. Bump iPhones. --- .github/workflows/swift.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index a4eb126..b0db8a3 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -7,7 +7,7 @@ on: branches: [main] jobs: - build_xcode_tahoe: + build_xcode_latest: runs-on: macos-26 steps: @@ -16,9 +16,9 @@ jobs: xcode-version: latest-stable - uses: actions/checkout@v4 - name: Build TGCardVC - run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' + run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 16' - build_xcode_sequoia: + build_xcode_previous: runs-on: macos-15 steps: - uses: maxim-lobanov/setup-xcode@v1 @@ -26,7 +26,7 @@ jobs: xcode-version: latest-stable - uses: actions/checkout@v4 - name: Build TGCardVC - run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 14' + run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 16' examples: runs-on: macos-15 @@ -39,4 +39,4 @@ jobs: - name: Build Example run: | cd Example - xcodebuild build -scheme 'Example' -destination 'platform=iOS Simulator,name=iPhone 14' + xcodebuild build -scheme 'Example' -destination 'platform=iOS Simulator,name=iPhone 16' From f680226bf41520c24d70835b3d70ad3ae0e4b832 Mon Sep 17 00:00:00 2001 From: Adrian Schoenig Date: Thu, 9 Oct 2025 14:14:25 +1100 Subject: [PATCH 25/25] Tahoe can test against iPhone 17 --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index b0db8a3..98b3d50 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -16,7 +16,7 @@ jobs: xcode-version: latest-stable - uses: actions/checkout@v4 - name: Build TGCardVC - run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 16' + run: xcodebuild -workspace . -scheme TGCardViewController -destination 'platform=iOS Simulator,name=iPhone 17' build_xcode_previous: runs-on: macos-15