|
|
@@ -672,12 +672,16 @@ private final class PremiumPlansViewController: NSViewController {
|
|
|
title.font = .systemFont(ofSize: 40, weight: .semibold)
|
|
|
title.textColor = Theme.primaryText
|
|
|
title.alignment = .center
|
|
|
+ title.lineBreakMode = .byTruncatingTail
|
|
|
+ title.maximumNumberOfLines = 1
|
|
|
premiumTitleLabel = title
|
|
|
|
|
|
let subtitle = NSTextField(labelWithString: L("Unlock unlimited access to premium tools and boost your productivity."))
|
|
|
subtitle.font = .systemFont(ofSize: 14, weight: .regular)
|
|
|
subtitle.textColor = Theme.secondaryText
|
|
|
subtitle.alignment = .center
|
|
|
+ subtitle.lineBreakMode = .byWordWrapping
|
|
|
+ subtitle.maximumNumberOfLines = 2
|
|
|
premiumSubtitleLabel = subtitle
|
|
|
|
|
|
pricingCardTargets = []
|
|
|
@@ -696,12 +700,32 @@ private final class PremiumPlansViewController: NSViewController {
|
|
|
headerStack.spacing = 10
|
|
|
headerStack.alignment = .centerX
|
|
|
headerStack.translatesAutoresizingMaskIntoConstraints = false
|
|
|
-
|
|
|
- let bodyStack = NSStackView(views: [cardsRow, trustRow])
|
|
|
- bodyStack.orientation = .vertical
|
|
|
- bodyStack.spacing = 16
|
|
|
- bodyStack.alignment = .centerX
|
|
|
- bodyStack.translatesAutoresizingMaskIntoConstraints = false
|
|
|
+ headerStack.setContentHuggingPriority(.required, for: .vertical)
|
|
|
+ headerStack.setContentCompressionResistancePriority(.required, for: .vertical)
|
|
|
+
|
|
|
+ let paywallStack = NSStackView(views: [headerStack, cardsRow])
|
|
|
+ paywallStack.orientation = .vertical
|
|
|
+ paywallStack.spacing = 16
|
|
|
+ paywallStack.setCustomSpacing(12, after: headerStack)
|
|
|
+ paywallStack.alignment = .centerX
|
|
|
+ paywallStack.translatesAutoresizingMaskIntoConstraints = false
|
|
|
+ paywallStack.setContentHuggingPriority(.required, for: .vertical)
|
|
|
+ paywallStack.setContentCompressionResistancePriority(.required, for: .vertical)
|
|
|
+
|
|
|
+ let topFlex = NSView()
|
|
|
+ topFlex.translatesAutoresizingMaskIntoConstraints = false
|
|
|
+ topFlex.setContentHuggingPriority(.defaultLow, for: .vertical)
|
|
|
+ topFlex.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
|
|
|
+
|
|
|
+ let bottomFlex = NSView()
|
|
|
+ bottomFlex.translatesAutoresizingMaskIntoConstraints = false
|
|
|
+ bottomFlex.setContentHuggingPriority(.defaultLow, for: .vertical)
|
|
|
+ bottomFlex.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
|
|
|
+
|
|
|
+ let centeredColumn = NSStackView(views: [topFlex, paywallStack, bottomFlex])
|
|
|
+ centeredColumn.orientation = .vertical
|
|
|
+ centeredColumn.spacing = 0
|
|
|
+ centeredColumn.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
let scrollView = NSScrollView()
|
|
|
scrollView.hasVerticalScroller = true
|
|
|
@@ -713,23 +737,24 @@ private final class PremiumPlansViewController: NSViewController {
|
|
|
let scrollDocument = NSView()
|
|
|
scrollDocument.translatesAutoresizingMaskIntoConstraints = false
|
|
|
scrollView.documentView = scrollDocument
|
|
|
- scrollDocument.addSubview(bodyStack)
|
|
|
+ scrollDocument.addSubview(centeredColumn)
|
|
|
|
|
|
- view.addSubview(headerStack)
|
|
|
view.addSubview(scrollView)
|
|
|
+ view.addSubview(trustRow)
|
|
|
view.addSubview(footerRow)
|
|
|
view.addSubview(closeButton)
|
|
|
|
|
|
let scrollClip = scrollView.contentView
|
|
|
NSLayoutConstraint.activate([
|
|
|
- headerStack.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24),
|
|
|
- headerStack.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24),
|
|
|
- headerStack.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
|
|
|
-
|
|
|
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24),
|
|
|
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24),
|
|
|
- scrollView.topAnchor.constraint(equalTo: headerStack.bottomAnchor, constant: 12),
|
|
|
- scrollView.bottomAnchor.constraint(equalTo: footerRow.topAnchor, constant: -12),
|
|
|
+ scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
|
|
|
+ scrollView.bottomAnchor.constraint(equalTo: trustRow.topAnchor, constant: -16),
|
|
|
+
|
|
|
+ trustRow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24),
|
|
|
+ trustRow.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24),
|
|
|
+ trustRow.bottomAnchor.constraint(equalTo: footerRow.topAnchor, constant: -12),
|
|
|
+ trustRow.heightAnchor.constraint(equalToConstant: 72),
|
|
|
|
|
|
footerRow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24),
|
|
|
footerRow.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24),
|
|
|
@@ -740,15 +765,22 @@ private final class PremiumPlansViewController: NSViewController {
|
|
|
scrollDocument.trailingAnchor.constraint(equalTo: scrollClip.trailingAnchor),
|
|
|
scrollDocument.topAnchor.constraint(equalTo: scrollClip.topAnchor),
|
|
|
scrollDocument.widthAnchor.constraint(equalTo: scrollClip.widthAnchor),
|
|
|
- scrollDocument.bottomAnchor.constraint(equalTo: bodyStack.bottomAnchor, constant: 8),
|
|
|
-
|
|
|
- bodyStack.leadingAnchor.constraint(equalTo: scrollDocument.leadingAnchor),
|
|
|
- bodyStack.trailingAnchor.constraint(equalTo: scrollDocument.trailingAnchor),
|
|
|
- bodyStack.topAnchor.constraint(equalTo: scrollDocument.topAnchor, constant: 4),
|
|
|
- bodyStack.widthAnchor.constraint(equalTo: scrollDocument.widthAnchor),
|
|
|
-
|
|
|
- cardsRow.widthAnchor.constraint(equalTo: bodyStack.widthAnchor),
|
|
|
- trustRow.widthAnchor.constraint(equalTo: bodyStack.widthAnchor),
|
|
|
+ scrollDocument.bottomAnchor.constraint(equalTo: centeredColumn.bottomAnchor),
|
|
|
+ scrollDocument.heightAnchor.constraint(greaterThanOrEqualTo: scrollClip.heightAnchor),
|
|
|
+
|
|
|
+ centeredColumn.leadingAnchor.constraint(equalTo: scrollDocument.leadingAnchor),
|
|
|
+ centeredColumn.trailingAnchor.constraint(equalTo: scrollDocument.trailingAnchor),
|
|
|
+ centeredColumn.topAnchor.constraint(equalTo: scrollDocument.topAnchor),
|
|
|
+ centeredColumn.bottomAnchor.constraint(equalTo: scrollDocument.bottomAnchor),
|
|
|
+ centeredColumn.widthAnchor.constraint(equalTo: scrollDocument.widthAnchor),
|
|
|
+
|
|
|
+ topFlex.heightAnchor.constraint(equalTo: bottomFlex.heightAnchor),
|
|
|
+
|
|
|
+ paywallStack.widthAnchor.constraint(equalTo: centeredColumn.widthAnchor),
|
|
|
+ headerStack.widthAnchor.constraint(equalTo: paywallStack.widthAnchor),
|
|
|
+ title.widthAnchor.constraint(equalTo: headerStack.widthAnchor),
|
|
|
+ subtitle.widthAnchor.constraint(equalTo: headerStack.widthAnchor),
|
|
|
+ cardsRow.widthAnchor.constraint(equalTo: paywallStack.widthAnchor),
|
|
|
|
|
|
closeButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 14),
|
|
|
closeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -14),
|