Няма описание

CVFilledPreviewPageView.swift 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //
  2. // CVFilledPreviewPageView.swift
  3. // App for Indeed
  4. //
  5. // Full-screen preview of a profile merged into the selected CV template.
  6. //
  7. import Cocoa
  8. private final class CVPreviewFlippedDocumentView: NSView {
  9. override var isFlipped: Bool { true }
  10. }
  11. /// Hosts a scrollable `CVProfileDocumentView` with a simple chrome header and back navigation.
  12. final class CVFilledPreviewPageView: NSView {
  13. var onDismiss: (() -> Void)?
  14. private let backButton = NSButton(title: "← Profiles", target: nil, action: nil)
  15. private let titleLabel = NSTextField(labelWithString: "CV preview")
  16. private let scrollView = NSScrollView()
  17. private let documentView = CVPreviewFlippedDocumentView()
  18. private let contentStack = NSStackView()
  19. private static let pageBackground = NSColor(srgbRed: 1, green: 1, blue: 1, alpha: 1)
  20. private static let secondaryText = NSColor(srgbRed: 100 / 255, green: 116 / 255, blue: 139 / 255, alpha: 1)
  21. private static let brandBlue = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
  22. override init(frame frameRect: NSRect) {
  23. super.init(frame: frameRect)
  24. wantsLayer = true
  25. layer?.backgroundColor = Self.pageBackground.cgColor
  26. userInterfaceLayoutDirection = .leftToRight
  27. backButton.translatesAutoresizingMaskIntoConstraints = false
  28. backButton.bezelStyle = .rounded
  29. backButton.isBordered = false
  30. backButton.font = .systemFont(ofSize: 13, weight: .semibold)
  31. backButton.contentTintColor = Self.brandBlue
  32. backButton.target = self
  33. backButton.action = #selector(didTapBack)
  34. titleLabel.font = .systemFont(ofSize: 18, weight: .semibold)
  35. titleLabel.textColor = NSColor(srgbRed: 31 / 255, green: 41 / 255, blue: 55 / 255, alpha: 1)
  36. let subtitle = NSTextField(wrappingLabelWithString: "Your profile fields are laid out using the template you chose in CV Maker.")
  37. subtitle.font = .systemFont(ofSize: 12, weight: .regular)
  38. subtitle.textColor = Self.secondaryText
  39. subtitle.maximumNumberOfLines = 0
  40. let headerCol = NSStackView(views: [backButton, titleLabel, subtitle])
  41. headerCol.orientation = .vertical
  42. headerCol.alignment = .leading
  43. headerCol.spacing = 6
  44. headerCol.setCustomSpacing(14, after: backButton)
  45. headerCol.translatesAutoresizingMaskIntoConstraints = false
  46. contentStack.orientation = .vertical
  47. contentStack.alignment = .leading
  48. contentStack.spacing = 20
  49. contentStack.translatesAutoresizingMaskIntoConstraints = false
  50. documentView.translatesAutoresizingMaskIntoConstraints = false
  51. documentView.addSubview(contentStack)
  52. scrollView.translatesAutoresizingMaskIntoConstraints = false
  53. scrollView.drawsBackground = false
  54. scrollView.hasVerticalScroller = true
  55. scrollView.hasHorizontalScroller = false
  56. scrollView.autohidesScrollers = true
  57. scrollView.borderType = .noBorder
  58. scrollView.documentView = documentView
  59. addSubview(headerCol)
  60. addSubview(scrollView)
  61. NSLayoutConstraint.activate([
  62. headerCol.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32),
  63. headerCol.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32),
  64. headerCol.topAnchor.constraint(equalTo: topAnchor, constant: 16),
  65. scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
  66. scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
  67. scrollView.topAnchor.constraint(equalTo: headerCol.bottomAnchor, constant: 16),
  68. scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
  69. documentView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
  70. documentView.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor),
  71. documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
  72. documentView.bottomAnchor.constraint(equalTo: contentStack.bottomAnchor, constant: 40),
  73. contentStack.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 32),
  74. contentStack.trailingAnchor.constraint(lessThanOrEqualTo: documentView.trailingAnchor, constant: -32),
  75. contentStack.topAnchor.constraint(equalTo: documentView.topAnchor, constant: 8),
  76. contentStack.widthAnchor.constraint(lessThanOrEqualTo: documentView.widthAnchor, constant: -64)
  77. ])
  78. }
  79. @available(*, unavailable)
  80. required init?(coder: NSCoder) {
  81. fatalError("init(coder:) has not been implemented")
  82. }
  83. func configure(profile: SavedProfile, template: CVTemplate) {
  84. for v in contentStack.arrangedSubviews {
  85. contentStack.removeArrangedSubview(v)
  86. v.removeFromSuperview()
  87. }
  88. let doc = CVProfileDocumentView(profile: profile, template: template)
  89. contentStack.addArrangedSubview(doc)
  90. let profileTitle = profile.profileDisplayName.isEmpty ? "Untitled profile" : profile.profileDisplayName
  91. titleLabel.stringValue = "\(template.name) · \(profileTitle)"
  92. }
  93. @objc private func didTapBack() {
  94. onDismiss?()
  95. }
  96. }