Manos Chorianopoulos

MyRewardsProfileInfoTableViewCell redesign

...@@ -13,107 +13,144 @@ protocol MyRewardsProfileInfoTableViewCellDelegate: AnyObject { ...@@ -13,107 +13,144 @@ protocol MyRewardsProfileInfoTableViewCellDelegate: AnyObject {
13 13
14 @objc(MyRewardsProfileInfoTableViewCell) 14 @objc(MyRewardsProfileInfoTableViewCell)
15 public class MyRewardsProfileInfoTableViewCell: UITableViewCell { 15 public class MyRewardsProfileInfoTableViewCell: UITableViewCell {
16 - @IBOutlet weak var tagView1: UIView! 16 +
17 - @IBOutlet weak var tagLabel1: UILabel! 17 + // MARK: - IBOutlets
18 - @IBOutlet weak var tagView2: UIView! 18 +
19 - @IBOutlet weak var tagLabel2: UILabel! 19 + /// Bold "Rewards" title label (top-left)
20 - @IBOutlet weak var profileImage: UIImageView! 20 + @IBOutlet weak var titleLabel: UILabel!
21 +
22 + /// Horizontally scrollable container for tag pills
23 + @IBOutlet weak var tagsScrollView: UIScrollView!
24 +
25 + /// Horizontal stack view inside the scroll view; tag pill views are added here dynamically
26 + @IBOutlet weak var tagsStackView: UIStackView!
27 +
28 + /// Settings / gear button (top-right)
21 @IBOutlet weak var profileButton: UIButton! 29 @IBOutlet weak var profileButton: UIButton!
22 30
31 + // MARK: - Delegate
32 +
23 weak var delegate: MyRewardsProfileInfoTableViewCellDelegate? 33 weak var delegate: MyRewardsProfileInfoTableViewCellDelegate?
24 34
25 - // MARK: - Properties 35 + // MARK: - Private
36 +
26 private var profileModel: ProfileModel? 37 private var profileModel: ProfileModel?
27 38
39 + // MARK: - Lifecycle
40 +
28 public override func awakeFromNib() { 41 public override func awakeFromNib() {
29 super.awakeFromNib() 42 super.awakeFromNib()
30 - // Initialization code
31 43
32 - profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil) 44 + selectionStyle = .none
33 45
34 - profileButton.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside) 46 + // Title
47 + titleLabel.font = UIFont(name: "PingLCG-Bold", size: 26)
48 + ?? UIFont.boldSystemFont(ofSize: 26)
49 + titleLabel.textColor = UIColor(rgb: 0x1D2023)
50 + titleLabel.text = "Rewards"
35 51
36 - tagView1.backgroundColor = UIColor(rgb: 0x09914E) 52 + // Gear button: render image as-is (no tint) so the gray circle style is preserved
37 - tagView1.layer.cornerRadius = 4.0 53 + let gearImage = UIImage(named: "settings_circle", in: Bundle.frameworkResourceBundle, compatibleWith: nil)?
38 - tagLabel1.font = UIFont(name: "PingLCG-Regular", size: 17) 54 + .withRenderingMode(.alwaysOriginal)
39 - tagLabel1.textColor = UIColor(rgb: 0xFFFFFF) 55 + profileButton.setImage(gearImage, for: .normal)
56 + profileButton.setTitle("", for: .normal)
57 + profileButton.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside)
40 58
41 - tagView2.backgroundColor = UIColor(rgb: 0xFC9F25) 59 + // Tags scroll view
42 - tagView2.layer.cornerRadius = 4.0 60 + tagsScrollView.showsHorizontalScrollIndicator = false
43 - tagLabel2.font = UIFont(name: "PingLCG-Regular", size: 17) 61 + tagsScrollView.showsVerticalScrollIndicator = false
44 - tagLabel2.textColor = UIColor(rgb: 0xFFFFFF)
45 62
63 + // Tags stack view
64 + tagsStackView.axis = .horizontal
65 + tagsStackView.spacing = 9
66 + tagsStackView.alignment = .center
67 + tagsStackView.distribution = .fill
46 } 68 }
47 69
48 public override func setSelected(_ selected: Bool, animated: Bool) { 70 public override func setSelected(_ selected: Bool, animated: Bool) {
49 super.setSelected(selected, animated: animated) 71 super.setSelected(selected, animated: animated)
72 + }
50 73
51 - // Configure the view for the selected state 74 + public override func prepareForReuse() {
75 + super.prepareForReuse()
76 + clearTags()
52 } 77 }
53 78
79 + // MARK: - Actions
80 +
54 @objc private func profileButtonTapped() { 81 @objc private func profileButtonTapped() {
55 delegate?.didTapProfileButton() 82 delegate?.didTapProfileButton()
56 } 83 }
57 84
58 - // MARK: - Configuration Methods 85 + // MARK: - Configuration
59 86
60 public func configureCell(data: SectionModel?) { 87 public func configureCell(data: SectionModel?) {
61 guard let data = data, 88 guard let data = data,
62 - let itemType = data.itemType, 89 + data.sectionType == .myRewardsProfileInfo else {
63 - itemType == .profile else {
64 configureDefaultState() 90 configureDefaultState()
65 return 91 return
66 } 92 }
67 93
68 - // Check if we have real profile data
69 if let metadata = data.metadata, 94 if let metadata = data.metadata,
70 let profile = metadata["profile"] as? ProfileModel { 95 let profile = metadata["profile"] as? ProfileModel {
71 - // Configure with real profile data
72 configureCell(profile: profile) 96 configureCell(profile: profile)
73 } else { 97 } else {
74 - // Configure with default state (no profile data)
75 configureDefaultState() 98 configureDefaultState()
76 } 99 }
77 } 100 }
78 101
79 public func configureCell(profile: ProfileModel) { 102 public func configureCell(profile: ProfileModel) {
80 self.profileModel = profile 103 self.profileModel = profile
81 - 104 + populateTags(segments: profile._user_segments)
82 - // TODO: Configure tag labels with profile data
83 - // We need to determine what data should populate tagView1 and tagView2
84 - // Possible options from ProfileModel:
85 - // - _user_points (loyalty points)
86 - // - _badge (user badge/tier)
87 - // - _verified (verification status)
88 - // - Custom business logic based on profile data
89 -
90 - // For now, keep tags visible with current static styling
91 - tagView1.isHidden = false
92 - tagView2.isHidden = false
93 -
94 - // Load profile image if available
95 - if !profile._image_url.isEmpty {
96 - loadProfileImage(from: profile._image_url)
97 - } else {
98 - profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
99 - }
100 } 105 }
101 106
102 private func configureDefaultState() { 107 private func configureDefaultState() {
103 - // Default state: no profile data available
104 self.profileModel = nil 108 self.profileModel = nil
109 + clearTags()
110 + }
105 111
106 - // Keep tags visible even in default state 112 + // MARK: - Tag Helpers
107 - tagView1.isHidden = false
108 - tagView2.isHidden = false
109 113
110 - profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil) 114 + /// Removes all tag pill views from the stack view.
115 + private func clearTags() {
116 + tagsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
111 } 117 }
112 118
113 - private func loadProfileImage(from urlString: String) { 119 + /// Creates one pill view per segment string and adds them to the stack view.
114 - // For now, use default image - can be enhanced later with URL loading 120 + private func populateTags(segments: [String]) {
115 - profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil) 121 + clearTags()
122 +
123 + for segment in segments where !segment.isEmpty {
124 + let pill = makePillView(text: segment)
125 + tagsStackView.addArrangedSubview(pill)
126 + }
127 + }
116 128
117 - // TODO: Add dynamic profile picture and tags 129 + /// Builds a rounded pill view with the given text.
130 + private func makePillView(text: String) -> UIView {
131 + let container = UIView()
132 + container.backgroundColor = UIColor(rgb: 0xF1F2F4)
133 + container.layer.cornerRadius = 13
134 + container.clipsToBounds = true
135 +
136 + let label = UILabel()
137 + label.text = text
138 + label.font = UIFont(name: "PingLCG-Regular", size: 12)
139 + ?? UIFont.systemFont(ofSize: 12)
140 + label.textColor = UIColor(rgb: 0x00111B)
141 + label.numberOfLines = 1
142 + label.translatesAutoresizingMaskIntoConstraints = false
143 +
144 + container.addSubview(label)
145 + container.translatesAutoresizingMaskIntoConstraints = false
146 +
147 + NSLayoutConstraint.activate([
148 + label.topAnchor.constraint(equalTo: container.topAnchor, constant: 6),
149 + label.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: -6),
150 + label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8),
151 + label.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -8)
152 + ])
153 +
154 + return container
118 } 155 }
119 } 156 }
......
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> 2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
3 <device id="retina6_12" orientation="portrait" appearance="light"/> 3 <device id="retina6_12" orientation="portrait" appearance="light"/>
4 <dependencies> 4 <dependencies>
5 - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/> 5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/>
6 <capability name="Safe area layout guides" minToolsVersion="9.0"/> 6 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
7 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 7 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
8 </dependencies> 8 </dependencies>
9 <objects> 9 <objects>
10 <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> 10 <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
11 <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> 11 <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
12 - <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="MyRewardsProfileInfoTableViewCell" rowHeight="141" id="KGk-i7-Jjw" customClass="MyRewardsProfileInfoTableViewCell"> 12 + <tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="MyRewardsProfileInfoTableViewCell" id="KGk-i7-Jjw" customClass="MyRewardsProfileInfoTableViewCell">
13 - <rect key="frame" x="0.0" y="0.0" width="318" height="141"/> 13 + <rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
14 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> 14 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
15 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM"> 15 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
16 - <rect key="frame" x="0.0" y="0.0" width="318" height="141"/> 16 + <rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
17 <autoresizingMask key="autoresizingMask"/> 17 <autoresizingMask key="autoresizingMask"/>
18 <subviews> 18 <subviews>
19 - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GrG-Na-dBF" userLabel="Parent View"> 19 + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Rewards" textAlignment="natural" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ttl-lb-001" userLabel="TitleLabel">
20 - <rect key="frame" x="0.0" y="0.0" width="318" height="130.33333333333334"/> 20 + <rect key="frame" x="17.999999999999993" y="24" width="109.33333333333331" height="24"/>
21 - <subviews>
22 - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Uzq-sj-DeG" userLabel="Top View">
23 - <rect key="frame" x="24" y="35.999999999999993" width="270" height="94.333333333333314"/>
24 - <subviews>
25 - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iZR-9I-qrq">
26 - <rect key="frame" x="0.0" y="34.333333333333329" width="58" height="26"/>
27 - <subviews>
28 - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Green" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HbR-qg-oZj">
29 - <rect key="frame" x="6" y="3" width="46" height="20"/>
30 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 21 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
31 - <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/> 22 + <fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="26"/>
32 - <nil key="textColor"/> 23 + <color key="textColor" red="0.067000000000000004" green="0.067000000000000004" blue="0.067000000000000004" alpha="1" colorSpace="calibratedRGB"/>
33 <nil key="highlightedColor"/> 24 <nil key="highlightedColor"/>
34 </label> 25 </label>
35 - </subviews>
36 - <color key="backgroundColor" red="0.035294117649999998" green="0.56862745100000001" blue="0.30588235289999999" alpha="1" colorSpace="calibratedRGB"/>
37 - <constraints>
38 - <constraint firstAttribute="trailing" secondItem="HbR-qg-oZj" secondAttribute="trailing" constant="6" id="D5p-jO-24v"/>
39 - <constraint firstItem="HbR-qg-oZj" firstAttribute="leading" secondItem="iZR-9I-qrq" secondAttribute="leading" constant="6" id="LFh-ia-T2B"/>
40 - <constraint firstItem="HbR-qg-oZj" firstAttribute="top" secondItem="iZR-9I-qrq" secondAttribute="top" constant="3" id="RhN-3V-CNu"/>
41 - <constraint firstAttribute="bottom" secondItem="HbR-qg-oZj" secondAttribute="bottom" constant="3" id="aPc-Uy-H9c"/>
42 - </constraints>
43 - </view>
44 - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uq8-95-vyl">
45 - <rect key="frame" x="66" y="34.333333333333329" width="61.666666666666657" height="26"/>
46 - <subviews>
47 - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Family" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UDU-LU-kJf">
48 - <rect key="frame" x="6" y="3" width="49.666666666666664" height="20"/>
49 - <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
50 - <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
51 - <nil key="textColor"/>
52 - <nil key="highlightedColor"/>
53 - </label>
54 - </subviews>
55 - <color key="backgroundColor" red="0.98823529409999999" green="0.62352941179999999" blue="0.1450980392" alpha="1" colorSpace="calibratedRGB"/>
56 - <constraints>
57 - <constraint firstAttribute="trailing" secondItem="UDU-LU-kJf" secondAttribute="trailing" constant="6" id="Ann-r9-abe"/>
58 - <constraint firstItem="UDU-LU-kJf" firstAttribute="top" secondItem="uq8-95-vyl" secondAttribute="top" constant="3" id="cUu-IO-JNt"/>
59 - <constraint firstAttribute="bottom" secondItem="UDU-LU-kJf" secondAttribute="bottom" constant="3" id="dIU-Z8-BrZ"/>
60 - <constraint firstItem="UDU-LU-kJf" firstAttribute="leading" secondItem="uq8-95-vyl" secondAttribute="leading" constant="6" id="vb0-4P-dZE"/>
61 - </constraints>
62 - </view>
63 - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="D1N-l1-zYb">
64 - <rect key="frame" x="227" y="0.0" width="43" height="94.333333333333329"/>
65 - <subviews>
66 - <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ksj-lM-RAp">
67 - <rect key="frame" x="0.0" y="0.0" width="43" height="43"/>
68 - <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
69 - <constraints>
70 - <constraint firstAttribute="width" constant="43" id="MsB-3N-rp3"/>
71 - <constraint firstAttribute="height" constant="43" id="UVr-zI-nCH"/>
72 - </constraints>
73 - </imageView>
74 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PEZ-e6-PaN" userLabel="ProfileButton"> 26 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PEZ-e6-PaN" userLabel="ProfileButton">
75 - <rect key="frame" x="0.0" y="0.0" width="43" height="94.333333333333329"/> 27 + <rect key="frame" x="309" y="12" width="48" height="48"/>
76 - <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
77 - <state key="normal" title="Button"/>
78 - <buttonConfiguration key="configuration" style="plain" title="Button">
79 - <color key="baseForegroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
80 - </buttonConfiguration>
81 - </button>
82 - </subviews>
83 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 28 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
84 <constraints> 29 <constraints>
85 - <constraint firstAttribute="trailing" secondItem="PEZ-e6-PaN" secondAttribute="trailing" id="0Bs-BN-BYr"/> 30 + <constraint firstAttribute="height" constant="48" id="Btn-h-001"/>
86 - <constraint firstItem="ksj-lM-RAp" firstAttribute="top" secondItem="D1N-l1-zYb" secondAttribute="top" id="72b-ae-wwu"/> 31 + <constraint firstAttribute="width" constant="48" id="Btn-w-001"/>
87 - <constraint firstItem="PEZ-e6-PaN" firstAttribute="leading" secondItem="D1N-l1-zYb" secondAttribute="leading" id="JDf-Bc-agp"/>
88 - <constraint firstAttribute="bottom" secondItem="ksj-lM-RAp" secondAttribute="bottom" id="JVS-lc-V1a"/>
89 - <constraint firstAttribute="bottom" secondItem="PEZ-e6-PaN" secondAttribute="bottom" id="UsX-dl-5BF"/>
90 - <constraint firstAttribute="trailing" secondItem="ksj-lM-RAp" secondAttribute="trailing" id="VMk-Qb-GcZ"/>
91 - <constraint firstItem="ksj-lM-RAp" firstAttribute="leading" secondItem="D1N-l1-zYb" secondAttribute="leading" id="noX-0V-w67"/>
92 - <constraint firstItem="PEZ-e6-PaN" firstAttribute="top" secondItem="D1N-l1-zYb" secondAttribute="top" id="zU6-UR-WGM"/>
93 </constraints> 32 </constraints>
94 - </view> 33 + <state key="normal" title=""/>
95 - </subviews> 34 + </button>
35 + <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Scr-tv-001" userLabel="TagsScrollView">
36 + <rect key="frame" x="24" y="60" width="279" height="28"/>
37 + <subviews>
38 + <stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Stk-tv-001" userLabel="TagsStackView">
39 + <rect key="frame" x="0.0" y="0.0" width="0.0" height="28"/>
96 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 40 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
97 - <constraints> 41 + </stackView>
98 - <constraint firstItem="D1N-l1-zYb" firstAttribute="top" secondItem="Uzq-sj-DeG" secondAttribute="top" id="2Pg-pB-HXM"/>
99 - <constraint firstAttribute="trailing" secondItem="D1N-l1-zYb" secondAttribute="trailing" id="TIg-op-IhZ"/>
100 - <constraint firstItem="iZR-9I-qrq" firstAttribute="centerY" secondItem="Uzq-sj-DeG" secondAttribute="centerY" id="Xj6-Va-Vu6"/>
101 - <constraint firstItem="uq8-95-vyl" firstAttribute="leading" secondItem="iZR-9I-qrq" secondAttribute="trailing" constant="8" id="cFB-Jw-8CI"/>
102 - <constraint firstItem="uq8-95-vyl" firstAttribute="centerY" secondItem="Uzq-sj-DeG" secondAttribute="centerY" id="lpD-GB-qJb"/>
103 - <constraint firstItem="iZR-9I-qrq" firstAttribute="leading" secondItem="Uzq-sj-DeG" secondAttribute="leading" id="nqO-fC-fCW"/>
104 - <constraint firstItem="D1N-l1-zYb" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="uq8-95-vyl" secondAttribute="trailing" constant="8" id="yWz-PS-7AW"/>
105 - <constraint firstAttribute="bottom" secondItem="D1N-l1-zYb" secondAttribute="bottom" id="zP0-l8-HZz"/>
106 - </constraints>
107 - </view>
108 </subviews> 42 </subviews>
109 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 43 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
110 <constraints> 44 <constraints>
111 - <constraint firstAttribute="trailing" secondItem="Uzq-sj-DeG" secondAttribute="trailing" constant="24" id="6Cb-JD-fEd"/> 45 + <constraint firstItem="Stk-tv-001" firstAttribute="leading" secondItem="Scr-tv-001" secondAttribute="leading" id="Scr-c-001"/>
112 - <constraint firstItem="Uzq-sj-DeG" firstAttribute="top" secondItem="GrG-Na-dBF" secondAttribute="top" constant="36" id="a4m-JH-bDa"/> 46 + <constraint firstItem="Stk-tv-001" firstAttribute="trailing" secondItem="Scr-tv-001" secondAttribute="trailing" id="Scr-c-002"/>
113 - <constraint firstItem="Uzq-sj-DeG" firstAttribute="leading" secondItem="GrG-Na-dBF" secondAttribute="leading" constant="24" id="bJt-81-pTc"/> 47 + <constraint firstItem="Stk-tv-001" firstAttribute="top" secondItem="Scr-tv-001" secondAttribute="top" id="Scr-c-003"/>
114 - <constraint firstAttribute="bottom" secondItem="Uzq-sj-DeG" secondAttribute="bottom" id="cjl-n6-BBf"/> 48 + <constraint firstItem="Stk-tv-001" firstAttribute="bottom" secondItem="Scr-tv-001" secondAttribute="bottom" id="Scr-c-004"/>
49 + <constraint firstItem="Stk-tv-001" firstAttribute="height" secondItem="Scr-tv-001" secondAttribute="height" id="Scr-c-005"/>
115 </constraints> 50 </constraints>
116 - </view> 51 + </scrollView>
117 </subviews> 52 </subviews>
118 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 53 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
119 <constraints> 54 <constraints>
120 - <constraint firstItem="GrG-Na-dBF" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="6vh-eL-qMw"/> 55 + <constraint firstAttribute="trailing" secondItem="PEZ-e6-PaN" secondAttribute="trailing" constant="18" id="Con-btn-001"/>
121 - <constraint firstAttribute="trailing" secondItem="GrG-Na-dBF" secondAttribute="trailing" id="Mhv-wX-J42"/> 56 + <constraint firstItem="PEZ-e6-PaN" firstAttribute="centerY" secondItem="Ttl-lb-001" secondAttribute="centerY" id="Con-btn-002"/>
122 - <constraint firstAttribute="bottom" secondItem="GrG-Na-dBF" secondAttribute="bottom" id="WfG-lv-Uw7"/> 57 + <constraint firstItem="Scr-tv-001" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="18" id="Con-scr-001"/>
123 - <constraint firstItem="GrG-Na-dBF" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="iSV-2N-pbv"/> 58 + <constraint firstItem="Scr-tv-001" firstAttribute="top" secondItem="Ttl-lb-001" secondAttribute="bottom" constant="12" id="Con-scr-002"/>
59 + <constraint firstItem="Scr-tv-001" firstAttribute="height" constant="28" id="Con-scr-004"/>
60 + <constraint firstAttribute="bottom" secondItem="Scr-tv-001" secondAttribute="bottom" constant="12" id="Con-scr-005"/>
61 + <constraint firstItem="Ttl-lb-001" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="18" id="Con-tl-001"/>
62 + <constraint firstItem="Ttl-lb-001" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="24" id="Con-tl-002"/>
63 + <constraint firstItem="PEZ-e6-PaN" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ttl-lb-001" secondAttribute="trailing" constant="8" id="Con-tl-003"/>
64 + <constraint firstAttribute="trailing" secondItem="Scr-tv-001" secondAttribute="trailing" constant="18" id="SXS-cd-zKP"/>
124 </constraints> 65 </constraints>
125 </tableViewCellContentView> 66 </tableViewCellContentView>
126 <viewLayoutGuide key="safeArea" id="njF-e1-oar"/> 67 <viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
127 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 68 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
128 <connections> 69 <connections>
129 <outlet property="profileButton" destination="PEZ-e6-PaN" id="FBL-8U-9OZ"/> 70 <outlet property="profileButton" destination="PEZ-e6-PaN" id="FBL-8U-9OZ"/>
130 - <outlet property="profileImage" destination="ksj-lM-RAp" id="lwv-9G-Mmy"/> 71 + <outlet property="tagsScrollView" destination="Scr-tv-001" id="Out-scr-001"/>
131 - <outlet property="tagLabel1" destination="HbR-qg-oZj" id="Ggl-NO-w2a"/> 72 + <outlet property="tagsStackView" destination="Stk-tv-001" id="Out-stk-001"/>
132 - <outlet property="tagLabel2" destination="UDU-LU-kJf" id="Tc6-yb-xi1"/> 73 + <outlet property="titleLabel" destination="Ttl-lb-001" id="Out-tl-001"/>
133 - <outlet property="tagView1" destination="iZR-9I-qrq" id="EtM-Q0-Ru9"/>
134 - <outlet property="tagView2" destination="uq8-95-vyl" id="mP6-vQ-GY6"/>
135 </connections> 74 </connections>
136 <point key="canvasLocation" x="41.221374045801525" y="29.929577464788736"/> 75 <point key="canvasLocation" x="41.221374045801525" y="29.929577464788736"/>
137 </tableViewCell> 76 </tableViewCell>
......