Skip to content

Commit 078d00d

Browse files
authored
Course list new progress with certificate (#1108)
* Initial commit * Add progress text label * Add certificate threshold point view * Add certificate threshold value view * Update constraints
1 parent 7eedb86 commit 078d00d

12 files changed

+571
-54
lines changed

Stepic.xcodeproj/project.pbxproj

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@
884884
2C9959FD25F758EC00459588 /* ReviewSessionDataPlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9959FC25F758EC00459588 /* ReviewSessionDataPlainObject.swift */; };
885885
2C995A0725F765DF00459588 /* ReviewDataPlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C995A0625F765DF00459588 /* ReviewDataPlainObject.swift */; };
886886
2C998AD0246EC83800AAFDE4 /* NotificationAlertsAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C998ACF246EC83800AAFDE4 /* NotificationAlertsAnalytics.swift */; };
887+
2C99BC7827A3DA1100DAC033 /* CourseWidgetProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C99BC7727A3DA1100DAC033 /* CourseWidgetProgressView.swift */; };
887888
2C9A2DB525501B3C003AAD2E /* CourseListFilterQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9A2DB425501B3B003AAD2E /* CourseListFilterQuery.swift */; };
888889
2C9A8D2E22D348A5009434DB /* String+HTMLEscape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9A8D2D22D348A5009434DB /* String+HTMLEscape.swift */; };
889890
2C9BBE4124903AB500FFED49 /* UserCoursesObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9BBE4024903AB500FFED49 /* UserCoursesObserver.swift */; };
@@ -1060,6 +1061,8 @@
10601061
2CC5AA71242A34FA00C09F94 /* AdaptiveStatsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC5AA6E242A34F900C09F94 /* AdaptiveStatsManager.swift */; };
10611062
2CC5AA72242A34FA00C09F94 /* AdaptiveRatingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC5AA6F242A34FA00C09F94 /* AdaptiveRatingHelper.swift */; };
10621063
2CC5AA74242A351100C09F94 /* TapProxyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC5AA73242A351100C09F94 /* TapProxyView.swift */; };
1064+
2CC6ED3727A428E800E01068 /* CourseWidgetProgressCertificateThresholdPointView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC6ED3627A428E800E01068 /* CourseWidgetProgressCertificateThresholdPointView.swift */; };
1065+
2CC6ED3927A4557100E01068 /* CourseWidgetProgressCertificateThresholdValueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC6ED3827A4557100E01068 /* CourseWidgetProgressCertificateThresholdValueView.swift */; };
10631066
2CC8322B27561A4C00F525F6 /* WishlistRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC8322A27561A4C00F525F6 /* WishlistRepository.swift */; };
10641067
2CC8678725E1504000762416 /* SubmissionsFilterQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC8678625E1504000762416 /* SubmissionsFilterQuery.swift */; };
10651068
2CCB4B1526E76F220056C44E /* AnnouncementPlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCB4B1426E76F220056C44E /* AnnouncementPlainObject.swift */; };
@@ -2910,6 +2913,7 @@
29102913
2C995A0625F765DF00459588 /* ReviewDataPlainObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewDataPlainObject.swift; sourceTree = "<group>"; };
29112914
2C995A1D25F7968B00459588 /* Model_submissions_review_v72.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model_submissions_review_v72.xcdatamodel; sourceTree = "<group>"; };
29122915
2C998ACF246EC83800AAFDE4 /* NotificationAlertsAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationAlertsAnalytics.swift; sourceTree = "<group>"; };
2916+
2C99BC7727A3DA1100DAC033 /* CourseWidgetProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseWidgetProgressView.swift; sourceTree = "<group>"; };
29132917
2C9A2DB425501B3B003AAD2E /* CourseListFilterQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseListFilterQuery.swift; sourceTree = "<group>"; };
29142918
2C9A3C2525E7A85F005A04F8 /* Model_lesson_courses_units_array_v71.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model_lesson_courses_units_array_v71.xcdatamodel; sourceTree = "<group>"; };
29152919
2C9A8D2D22D348A5009434DB /* String+HTMLEscape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HTMLEscape.swift"; sourceTree = "<group>"; };
@@ -3100,6 +3104,8 @@
31003104
2CC5AA6E242A34F900C09F94 /* AdaptiveStatsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveStatsManager.swift; sourceTree = "<group>"; };
31013105
2CC5AA6F242A34FA00C09F94 /* AdaptiveRatingHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveRatingHelper.swift; sourceTree = "<group>"; };
31023106
2CC5AA73242A351100C09F94 /* TapProxyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TapProxyView.swift; sourceTree = "<group>"; };
3107+
2CC6ED3627A428E800E01068 /* CourseWidgetProgressCertificateThresholdPointView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseWidgetProgressCertificateThresholdPointView.swift; sourceTree = "<group>"; };
3108+
2CC6ED3827A4557100E01068 /* CourseWidgetProgressCertificateThresholdValueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseWidgetProgressCertificateThresholdValueView.swift; sourceTree = "<group>"; };
31033109
2CC8322A27561A4C00F525F6 /* WishlistRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WishlistRepository.swift; sourceTree = "<group>"; };
31043110
2CC8678625E1504000762416 /* SubmissionsFilterQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubmissionsFilterQuery.swift; sourceTree = "<group>"; };
31053111
2CC8683624CAD452004845AB /* Model_new_profile_organization_v57.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model_new_profile_organization_v57.xcdatamodel; sourceTree = "<group>"; };
@@ -5538,6 +5544,15 @@
55385544
path = SearchQueryResult;
55395545
sourceTree = "<group>";
55405546
};
5547+
2C99BC7627A3D9C300DAC033 /* Stats */ = {
5548+
isa = PBXGroup;
5549+
children = (
5550+
62E98E718321FFBD61C5A671 /* CourseWidgetStatsItemView.swift */,
5551+
62E98C0BB290D5BFB0F69A2E /* CourseWidgetStatsView.swift */,
5552+
);
5553+
path = Stats;
5554+
sourceTree = "<group>";
5555+
};
55415556
2C99D087238967FD00078D2B /* Events */ = {
55425557
isa = PBXGroup;
55435558
children = (
@@ -6698,6 +6713,16 @@
66986713
path = Section;
66996714
sourceTree = "<group>";
67006715
};
6716+
2CC6ED3527A428BA00E01068 /* Progress */ = {
6717+
isa = PBXGroup;
6718+
children = (
6719+
2CC6ED3627A428E800E01068 /* CourseWidgetProgressCertificateThresholdPointView.swift */,
6720+
2CC6ED3827A4557100E01068 /* CourseWidgetProgressCertificateThresholdValueView.swift */,
6721+
2C99BC7727A3DA1100DAC033 /* CourseWidgetProgressView.swift */,
6722+
);
6723+
path = Progress;
6724+
sourceTree = "<group>";
6725+
};
67016726
2CCB4B1626E7724E0056C44E /* Announcements */ = {
67026727
isa = PBXGroup;
67036728
children = (
@@ -9409,11 +9434,11 @@
94099434
62E98A35E88BBE09B6D20E70 /* CourseWidgetCoverView.swift */,
94109435
62E986B68558033E8B3DDF6A /* CourseWidgetLabel.swift */,
94119436
2CABB841267B929C0070E5E7 /* CourseWidgetPriceView.swift */,
9412-
62E98E718321FFBD61C5A671 /* CourseWidgetStatsItemView.swift */,
9413-
62E98C0BB290D5BFB0F69A2E /* CourseWidgetStatsView.swift */,
94149437
62E981558CAEBFB426F04DD2 /* CourseWidgetView.swift */,
94159438
2CB9EE8025CD68E70042AAD7 /* SeeAllCourseWidgetView.swift */,
94169439
2C2E44D024FE3FBF006B7303 /* SmallCourseWidgetView.swift */,
9440+
2CC6ED3527A428BA00E01068 /* Progress */,
9441+
2C99BC7627A3D9C300DAC033 /* Stats */,
94179442
);
94189443
path = Widget;
94199444
sourceTree = "<group>";
@@ -11172,6 +11197,7 @@
1117211197
2C4436B321356D960084489C /* CourseSubscriber.swift in Sources */,
1117311198
2C8BCC2624869A3400DFB009 /* NewProfileDetailsView.swift in Sources */,
1117411199
2C42EFB62476F28B00423695 /* MagicLinksAPI.swift in Sources */,
11200+
2CC6ED3927A4557100E01068 /* CourseWidgetProgressCertificateThresholdValueView.swift in Sources */,
1117511201
0806B2C21EBDBB0200FDE0F7 /* PostViewsExecutableTask.swift in Sources */,
1117611202
2C20C86222F8E1DE0052E9BF /* CodeTemplatePlainObject.swift in Sources */,
1117711203
2C1948B626298455007D3486 /* FLEXManager.swift in Sources */,
@@ -11973,6 +11999,7 @@
1197311999
62E98212665FE6C08C3736DA /* CourseInfoTabSyllabusHeaderView.swift in Sources */,
1197412000
62E988C6B635993C63C66666 /* CourseInfoTabSyllabusSectionDeadlinesView.swift in Sources */,
1197512001
2C9A2DB525501B3C003AAD2E /* CourseListFilterQuery.swift in Sources */,
12002+
2CC6ED3727A428E800E01068 /* CourseWidgetProgressCertificateThresholdPointView.swift in Sources */,
1197612003
62E9871420FDD64DCD4E4311 /* CourseInfoTabSyllabusSectionView.swift in Sources */,
1197712004
62E981A7F5DDECC573671FDE /* CourseListAssembly.swift in Sources */,
1197812005
2CB113B0259205D60093B572 /* StoryPartsReactionsPersistenceService.swift in Sources */,
@@ -12002,6 +12029,7 @@
1200212029
62E98B5E1705E2F3274D19EC /* CourseListCollectionViewDataSource.swift in Sources */,
1200312030
62E98A68DC04104ACC599EDD /* CourseListCollectionViewDelegate.swift in Sources */,
1200412031
62E987E3FA0C01DA74F90B91 /* CourseListColorMode.swift in Sources */,
12032+
2C99BC7827A3DA1100DAC033 /* CourseWidgetProgressView.swift in Sources */,
1200512033
2CCDD1FE24DBB35700A48EE0 /* Protected.swift in Sources */,
1200612034
62E98BB34B2B0C1B988F2A24 /* CourseListView.swift in Sources */,
1200712035
62E98CF698823997CBF8E919 /* CourseListViewDelegate.swift in Sources */,

Stepic/Sources/Helpers/FormatterHelper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ enum FormatterHelper {
2929
/// Format Progress's score value with 2 decimal points if has decimals; 0.123456 -> "0.12", 1.0 -> "1"
3030
static func progressScore(_ score: Float) -> String {
3131
let hasDecimals = score.truncatingRemainder(dividingBy: 1) != 0
32-
return hasDecimals ? String(format: "%.2f", score) : "\(Int(score))"
32+
if hasDecimals {
33+
let result = String(format: "%.2f", score)
34+
return result.last == "0" ? String(result.dropLast()) : result
35+
}
36+
return "\(Int(score))"
3337
}
3438

3539
/// Format Submission's score with 2 decimal points if has decimals; 0.75 -> "0.75", 1.0 -> "1"

Stepic/Sources/Modules/CourseList/CourseListPresenter.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,19 @@ final class CourseListPresenter: CourseListPresenterProtocol {
8282
return viewModels
8383
}
8484

85-
private func makeProgressViewModel(progress: Progress) -> CourseWidgetProgressViewModel {
86-
var normalizedPercent = progress.percentPassed
87-
normalizedPercent.round(.up)
85+
private func makeProgressViewModel(progress: Progress, course: Course) -> CourseWidgetProgressViewModel {
86+
let progressValue = progress.cost > 0
87+
? progress.score / Float(progress.cost)
88+
: 1
8889

8990
return CourseWidgetProgressViewModel(
90-
progress: normalizedPercent / 100.0,
91-
progressLabelText: "\(FormatterHelper.progressScore(progress.score))/\(progress.cost)"
91+
score: progress.score,
92+
cost: progress.cost,
93+
progress: progressValue,
94+
progressLabelText: "\(FormatterHelper.progressScore(progress.score))/\(progress.cost)",
95+
isWithCertificate: course.isWithCertificate,
96+
certificateRegularThreshold: course.certificateRegularThreshold,
97+
certificateDistinctionThreshold: course.certificateDistinctionThreshold
9298
)
9399
}
94100

@@ -112,7 +118,7 @@ final class CourseListPresenter: CourseListPresenterProtocol {
112118

113119
var progressViewModel: CourseWidgetProgressViewModel?
114120
if let progress = course.progress {
115-
progressViewModel = self.makeProgressViewModel(progress: progress)
121+
progressViewModel = self.makeProgressViewModel(progress: progress, course: course)
116122
}
117123

118124
var userCourseViewModel: CourseWidgetUserCourseViewModel?

Stepic/Sources/Modules/CourseList/CourseWidgetViewModel.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import UIKit
22

33
struct CourseWidgetProgressViewModel {
4+
let score: Float
5+
let cost: Int
6+
47
let progress: Float
58
let progressLabelText: String
9+
10+
let isWithCertificate: Bool
11+
let certificateRegularThreshold: Int?
12+
let certificateDistinctionThreshold: Int?
613
}
714

815
struct CourseWidgetUserCourseViewModel {

Stepic/Sources/Modules/CourseList/Views/CourseListColorMode.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Foundation
1+
import UIKit
22

33
enum CourseListColorMode {
44
case light
@@ -88,6 +88,35 @@ extension CourseListColorMode {
8888
}
8989
}
9090

91+
var courseWidgetProgressViewAppearance: CourseWidgetProgressView.Appearance {
92+
let progressTextLabelTextColor = UIColor.stepikMaterialSecondaryText
93+
let progressBarTrackTintColor = UIColor.onSurface.withAlphaComponent(0.12)
94+
95+
var appearance = CourseWidgetProgressView.Appearance(
96+
progressTextLabelAppearance: .init(
97+
maxLinesCount: 1,
98+
font: Typography.caption1Font,
99+
textColor: progressTextLabelTextColor
100+
),
101+
progressBarTrackTintColor: progressBarTrackTintColor
102+
)
103+
104+
switch self {
105+
case .light, .grouped:
106+
return appearance
107+
case .dark:
108+
appearance.progressTextLabelAppearance.textColor = .dynamic(
109+
light: .white.withAlphaComponent(0.6),
110+
dark: progressTextLabelTextColor
111+
)
112+
appearance.progressBarTrackTintColor = .dynamic(
113+
light: .white.withAlphaComponent(0.12),
114+
dark: progressBarTrackTintColor
115+
)
116+
return appearance
117+
}
118+
}
119+
91120
var courseWidgetTitleLabelAppearance: CourseWidgetLabel.Appearance {
92121
var appearance = CourseWidgetLabel.Appearance(
93122
maxLinesCount: 3,

Stepic/Sources/Modules/CourseList/Views/Widget/CourseWidgetView.swift

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ extension CourseWidgetView {
1818
let statsViewHeight: CGFloat = 17
1919
let statsViewInsets = LayoutInsets(top: 8)
2020

21+
let progressViewInsets = LayoutInsets(top: 8, right: 16)
22+
2123
let summaryLabelInsets = LayoutInsets(top: 12, left: 16, bottom: 16, right: 16)
2224
let priceViewInsets = LayoutInsets(top: 12, bottom: 17)
2325

@@ -48,6 +50,12 @@ final class CourseWidgetView: UIView, CourseWidgetViewProtocol {
4850
appearance: self.colorMode.courseWidgetStatsViewAppearance
4951
)
5052

53+
private lazy var progressView: CourseWidgetProgressView = {
54+
let view = CourseWidgetProgressView(appearance: self.colorMode.courseWidgetProgressViewAppearance)
55+
view.isHidden = true
56+
return view
57+
}()
58+
5159
private lazy var separatorView: UIView = {
5260
let view = UIView()
5361
view.backgroundColor = self.colorMode.courseWidgetBorderColor
@@ -114,14 +122,23 @@ final class CourseWidgetView: UIView, CourseWidgetViewProtocol {
114122

115123
let isArchived = viewModel.userCourse?.isArchived ?? false
116124
self.statsView.isArchived = isArchived
117-
self.statsView.progress = isArchived ? nil : viewModel.progress
118125

126+
self.updateProgressView(viewModel: isArchived ? nil : viewModel.progress)
119127
self.updatePriceView(viewModel: viewModel.price)
120128
self.updateBadgeImageView(viewModel: viewModel)
121129
}
122130

123131
func updateProgress(viewModel: CourseWidgetProgressViewModel) {
124-
self.statsView.progress = viewModel
132+
self.updateProgressView(viewModel: viewModel)
133+
}
134+
135+
// MARK: Private API
136+
137+
private func updateProgressView(viewModel: CourseWidgetProgressViewModel?) {
138+
if let viewModel = viewModel {
139+
self.progressView.configure(viewModel: viewModel)
140+
}
141+
self.progressView.isHidden = viewModel == nil
125142
}
126143

127144
private func updatePriceView(viewModel: CourseWidgetPriceViewModel?) {
@@ -159,8 +176,6 @@ final class CourseWidgetView: UIView, CourseWidgetViewProtocol {
159176
)
160177
}
161178

162-
// MARK: Private API
163-
164179
@objc
165180
private func continueLearningButtonClicked() {
166181
self.onContinueLearningButtonClick?()
@@ -177,6 +192,7 @@ extension CourseWidgetView: ProgrammaticallyInitializableViewProtocol {
177192
self.addSubview(self.titleLabel)
178193
self.addSubview(self.badgeImageView)
179194
self.addSubview(self.statsView)
195+
self.addSubview(self.progressView)
180196
self.addSubview(self.summaryLabel)
181197
self.addSubview(self.priceView)
182198
self.addSubview(self.continueLearningButton)
@@ -238,6 +254,21 @@ extension CourseWidgetView: ProgrammaticallyInitializableViewProtocol {
238254
.equalTo(self.appearance.statsViewHeight)
239255
}
240256

257+
self.progressView.translatesAutoresizingMaskIntoConstraints = false
258+
self.progressView.snp.makeConstraints { make in
259+
make.top
260+
.greaterThanOrEqualTo(self.titleLabel.snp.bottom)
261+
.offset(self.appearance.progressViewInsets.top)
262+
.priority(.low)
263+
make.leading
264+
.equalTo(self.titleLabel.snp.leading)
265+
make.bottom
266+
.equalTo(self.coverView.snp.bottom)
267+
make.trailing
268+
.equalToSuperview()
269+
.offset(-self.appearance.progressViewInsets.right)
270+
}
271+
241272
self.summaryLabel.translatesAutoresizingMaskIntoConstraints = false
242273
self.summaryLabel.snp.makeConstraints { make in
243274
make.top
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import SnapKit
2+
import UIKit
3+
4+
extension CourseWidgetProgressCertificateThresholdPointView {
5+
struct Appearance {
6+
let iconImageViewSize = CGSize(width: 6, height: 6)
7+
let iconImageViewTintColor = UIColor.white
8+
9+
let regularSize = CGSize(width: 6, height: 6)
10+
let doneSize = CGSize(width: 10, height: 10)
11+
12+
var backgroundColor = UIColor.stepikGreenFixed
13+
}
14+
}
15+
16+
final class CourseWidgetProgressCertificateThresholdPointView: UIView {
17+
let appearance: Appearance
18+
19+
private lazy var iconImageView: UIImageView = {
20+
let imageView = UIImageView(
21+
image: UIImage(named: "course-info-news-badge-correct")?.withRenderingMode(.alwaysTemplate)
22+
)
23+
imageView.contentMode = .scaleAspectFit
24+
imageView.tintColor = self.appearance.iconImageViewTintColor
25+
return imageView
26+
}()
27+
28+
var isDone = false {
29+
didSet {
30+
self.updateAppearance()
31+
32+
if oldValue != self.isDone {
33+
self.setNeedsLayout()
34+
self.layoutIfNeeded()
35+
}
36+
}
37+
}
38+
39+
override var intrinsicContentSize: CGSize {
40+
self.isDone ? self.appearance.doneSize : self.appearance.regularSize
41+
}
42+
43+
init(
44+
frame: CGRect = .zero,
45+
appearance: Appearance = Appearance()
46+
) {
47+
self.appearance = appearance
48+
super.init(frame: frame)
49+
50+
self.setupView()
51+
self.addSubviews()
52+
self.makeConstraints()
53+
54+
self.updateAppearance()
55+
}
56+
57+
@available(*, unavailable)
58+
required init?(coder aDecoder: NSCoder) {
59+
fatalError("init(coder:) has not been implemented")
60+
}
61+
62+
override func layoutSubviews() {
63+
super.layoutSubviews()
64+
65+
self.clipsToBounds = true
66+
self.layer.cornerRadius = self.bounds.height / 2
67+
}
68+
69+
private func updateAppearance() {
70+
self.iconImageView.isHidden = !self.isDone
71+
self.invalidateIntrinsicContentSize()
72+
}
73+
}
74+
75+
extension CourseWidgetProgressCertificateThresholdPointView: ProgrammaticallyInitializableViewProtocol {
76+
func setupView() {
77+
self.backgroundColor = self.appearance.backgroundColor
78+
}
79+
80+
func addSubviews() {
81+
self.addSubview(self.iconImageView)
82+
}
83+
84+
func makeConstraints() {
85+
self.iconImageView.translatesAutoresizingMaskIntoConstraints = false
86+
self.iconImageView.snp.makeConstraints { make in
87+
make.center.equalToSuperview()
88+
make.size.equalTo(self.appearance.iconImageViewSize)
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)