Skip to content

Commit

Permalink
Fix CGColors to update on trait collection changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mats-stripe committed Jan 29, 2025
1 parent f0ee717 commit d4a0ec3
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct FinancialConnectionsAppearance: Equatable {
static let spinnerNeutral: UIColor = .neutral200
static let warningLight: UIColor = .attention50
static let warning: UIColor = .attention300
static let shadow: UIColor = .dynamic(light: .black, dark: .neutral0)

// These colors change based on the manifest's theme.
let primary: UIColor
Expand Down Expand Up @@ -80,6 +81,10 @@ extension FinancialConnectionsAppearance.Colors {

// MARK: - Raw colors
private extension UIColor {
static var black: UIColor {
return UIColor(red: 0 / 255.0, green: 0 / 255.0, blue: 0 / 255.0, alpha: 1) // #000000
}

// MARK: Neutral
static var neutral0: UIColor {
return UIColor(red: 255 / 255.0, green: 255 / 255.0, blue: 255 / 255.0, alpha: 1) // #ffffff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ private let ellipsisViewWidth: CGFloat = 32.0
final class ConsentLogoView: UIView {

private var multipleDotView: UIView?
private var shadowLayers: [CALayer] = []

init(merchantLogo: [String], showsAnimatedDots: Bool) {
super.init(frame: .zero)
Expand All @@ -25,9 +26,9 @@ final class ConsentLogoView: UIView {
if merchantLogo.count == 2 || merchantLogo.count == 3 {
for i in 0..<merchantLogo.count {
let urlString = merchantLogo[i]
horizontalStackView.addArrangedSubview(
CreateRoundedLogoView(urlString: urlString)
)
let logoView = CreateRoundedLogoView(urlString: urlString)
self.shadowLayers.append(logoView.layer)
horizontalStackView.addArrangedSubview(logoView)

let isLastLogo = (i == merchantLogo.count - 1)
if !isLastLogo, showsAnimatedDots {
Expand Down Expand Up @@ -93,12 +94,22 @@ final class ConsentLogoView: UIView {
}
)
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

for shadow in shadowLayers {
shadow.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
}
}
}

private func CreateRoundedLogoView(urlString: String) -> UIView {
let cornerRadius: CGFloat = 16.0
let shadowContainerView = UIView()
shadowContainerView.layer.shadowColor = UIColor.black.cgColor
shadowContainerView.layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
shadowContainerView.layer.shadowOpacity = 0.18
shadowContainerView.layer.shadowOffset = CGSize(width: 0, height: 3)
shadowContainerView.layer.shadowRadius = 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class InstitutionPickerViewController: UIViewController {
private let dataSource: InstitutionDataSource
weak var delegate: InstitutionPickerViewControllerDelegate?

private var shadowLayer: CALayer?

private lazy var headerView: UIView = {
let verticalStackView = UIStackView(
arrangedSubviews: [
Expand Down Expand Up @@ -88,6 +90,7 @@ class InstitutionPickerViewController: UIViewController {
// appear IF the user scrolls up very quickly
height: -Self.headerAndSearchBarSpacing
)
self.shadowLayer = verticalStackView.layer
return verticalStackView
}()
private lazy var searchBar: InstitutionSearchBar = {
Expand Down Expand Up @@ -241,6 +244,14 @@ class InstitutionPickerViewController: UIViewController {
animated: true
)
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

shadowLayer?.shadowColor = FinancialConnectionsAppearance.Colors.background.cgColor
}
}

// MARK: - Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ protocol InstitutionSearchBarDelegate: AnyObject {
final class InstitutionSearchBar: UIView {

private let appearance: FinancialConnectionsAppearance
private var shadowLayer: CALayer?
weak var delegate: InstitutionSearchBarDelegate?
var text: String {
get {
Expand Down Expand Up @@ -180,6 +181,14 @@ final class InstitutionSearchBar: UIView {
height: 1 / UIScreen.main.nativeScale
)
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
}
}

// MARK: - UITextFieldDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ final class LinkAccountPickerNewAccountRowView: UIView {
@objc private func didTapView() {
self.didSelect()
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

layer.borderColor = FinancialConnectionsAppearance.Colors.borderNeutral.cgColor
}
}

private func CreateIconView(imageUrl: String, appearance: FinancialConnectionsAppearance) -> UIView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@ import Foundation
import UIKit

final class NetworkingLinkLoginWarmupBodyView: HitTestView {
var borderLayer: CALayer?

init(email: String) {
super.init(frame: .zero)
let emailView = CreateEmailView(email: email)
self.borderLayer = emailView.layer
addAndPinSubview(emailView)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

borderLayer?.borderColor = FinancialConnectionsAppearance.Colors.borderNeutral.cgColor
}
}

private func CreateEmailView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import WebKit
final class PrepaneImageView: UIView {

private let centeringView: UIView
private var imageLayer: CALayer?

init(imageURLString: String) {
// first we load an image (or GIF) into a WebView
let imageView = GIFImageView(gifUrlString: imageURLString)
// the WebView is surrounded by a background that imitates the GIF presented inside of a phone
let phoneBackgroundView = CreatePhoneBackgroundView(imageView: imageView)
let (phoneBackgroundView, imageLayer) = CreatePhoneBackgroundView(imageView: imageView)
self.imageLayer = imageLayer
// we center the phone+gif in the middle
let centeringView = CreateCenteringView(centeredView: phoneBackgroundView)
self.centeringView = centeringView
Expand Down Expand Up @@ -65,9 +67,18 @@ final class PrepaneImageView: UIView {
maskLayer.path = path
layer.mask = maskLayer
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

imageLayer?.borderColor = FinancialConnectionsAppearance.Colors.backgroundSecondary.cgColor
imageLayer?.shadowColor = FinancialConnectionsAppearance.Colors.borderNeutral.cgColor
}
}

private func CreatePhoneBackgroundView(imageView: UIView) -> UIView {
private func CreatePhoneBackgroundView(imageView: UIView) -> (UIView, CALayer) {
let containerView = UIView()
let borderWidth: CGFloat = 8
imageView.layer.borderWidth = borderWidth
Expand All @@ -84,7 +95,7 @@ private func CreatePhoneBackgroundView(imageView: UIView) -> UIView {
trailing: 0
)
)
return containerView
return (containerView, imageView.layer)
}

private func CreateCenteringView(centeredView: UIView) -> UIView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,7 @@ final class AccountPickerRowView: UIView {
private let didSelect: () -> Void
private var isSelected: Bool = false {
didSet {
layer.cornerRadius = 12
if isSelected {
layer.borderColor = appearance.colors.border.cgColor
layer.borderWidth = 2
let shadowWidthOffset: CGFloat = 0
layer.shadowPath = CGPath(
roundedRect: CGRect(x: shadowWidthOffset / 2, y: 0, width: bounds.width - shadowWidthOffset, height: bounds.height),
cornerWidth: layer.cornerRadius,
cornerHeight: layer.cornerRadius,
transform: nil
)
layer.shadowColor = UIColor.black.cgColor
layer.shadowRadius = 1.5 / UIScreen.main.nativeScale
layer.shadowOpacity = 0.23
layer.shadowOffset = CGSize(
width: 0,
height: 1 / UIScreen.main.nativeScale
)
} else {
layer.borderColor = FinancialConnectionsAppearance.Colors.borderNeutral.cgColor
layer.borderWidth = 1
layer.shadowOpacity = 0
}
updateLayer()
checkboxView.isSelected = isSelected
}
}
Expand Down Expand Up @@ -142,6 +120,40 @@ final class AccountPickerRowView: UIView {
@objc private func didTapView() {
self.didSelect()
}

private func updateLayer() {
layer.cornerRadius = 12
if isSelected {
layer.borderColor = appearance.colors.border.cgColor
layer.borderWidth = 2
let shadowWidthOffset: CGFloat = 0
layer.shadowPath = CGPath(
roundedRect: CGRect(x: shadowWidthOffset / 2, y: 0, width: bounds.width - shadowWidthOffset, height: bounds.height),
cornerWidth: layer.cornerRadius,
cornerHeight: layer.cornerRadius,
transform: nil
)
layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
layer.shadowRadius = 1.5 / UIScreen.main.nativeScale
layer.shadowOpacity = 0.23
layer.shadowOffset = CGSize(
width: 0,
height: 1 / UIScreen.main.nativeScale
)
} else {
layer.borderColor = FinancialConnectionsAppearance.Colors.borderNeutral.cgColor
layer.borderWidth = 1
layer.shadowOpacity = 0
}
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

updateLayer()
}
}

private func CreateHorizontalStackView(arrangedSubviews: [UIView]) -> UIStackView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import UIKit
extension StripeUICore.Button {
static func primary(appearance: FinancialConnectionsAppearance) -> StripeUICore.Button {
let button = Button(configuration: .financialConnectionsPrimary(appearance: appearance))
button.layer.shadowColor = UIColor.black.cgColor
button.layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
button.layer.shadowRadius = 5 / UIScreen.main.nativeScale
button.layer.shadowOpacity = 0.25
button.layer.shadowOffset = CGSize(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,12 @@ private class AutomaticShadowScrollView: UIScrollView {
shadowView.alpha = remainingFadeDistance / startFadingDistanceToBottom
}
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

shadowView?.layer.shadowColor = FinancialConnectionsAppearance.Colors.textDefault.cgColor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ final class RoundedTextField: UIView {
trailing: 16
)
containerStackView.layer.cornerRadius = 12
containerStackView.layer.shadowColor = UIColor.black.cgColor
containerStackView.layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
containerStackView.layer.shadowRadius = 2 / UIScreen.main.nativeScale
containerStackView.layer.shadowOpacity = 0.1
containerStackView.layer.shadowOffset = CGSize(
Expand Down Expand Up @@ -190,8 +190,6 @@ final class RoundedTextField: UIView {
}

private func updateBorder(highlighted: Bool) {
let highlighted = textField.isFirstResponder

if errorText != nil && !highlighted {
containerHorizontalStackView.layer.borderColor = FinancialConnectionsAppearance.Colors.textCritical.cgColor
containerHorizontalStackView.layer.borderWidth = 2.0
Expand All @@ -209,6 +207,15 @@ final class RoundedTextField: UIView {
@IBAction private func textFieldDidChange() {
delegate?.roundedTextField(self, textDidChange: text)
}

// CGColor's need to be manually updated when the system theme changes.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }

updateBorder(highlighted: textField.isFirstResponder)
containerHorizontalStackView.layer.shadowColor = FinancialConnectionsAppearance.Colors.shadow.cgColor
}
}

// MARK: - UITextFieldDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ extension PaymentMethodFormViewController: ElementDelegate {
analyticsHelper.logFormInteracted(paymentMethodTypeIdentifier: paymentMethodType.identifier)
delegate?.didUpdate(self)
animateHeightChange()

if let instantDebitsFormElement = form as? InstantDebitsPaymentMethodElement {
let incentive = instantDebitsFormElement.displayableIncentive

if let formHeaderView = headerView as? FormHeaderView {
// We already display a promo badge in the bank form, so we don't want
// to display another one in the header.
Expand Down

0 comments on commit d4a0ec3

Please sign in to comment.