Skip to content

Commit 254139f

Browse files
authored
Discussions refactoring (#491)
* Format code * Use Reusable & NibLoadable * Remove unused DiscussionWebTableViewCell * Remove Label group * Update DiscussionTableViewCell * Refactor rename DiscussionTableViewCells -> DiscussionTableViewCell * Remove unused DiscussionCellDelegate * Create Views group * Remove unused DiscussionUpdateDelegate * Sort Discussions group files by name * Update WriteCommentViewController * Format DiscussionAlertConstructor's code * Update LoadMoreTableViewCell * Update DiscussionAlertConstructor * Tmp for DiscussionsViewController * Init Discussions only with DiscussionsLegacyAssembly * Initial commit for DiscussionsPresenter * Sort Services group by name * Create DiscussionProxiesNetworkService * Create CommentsNetworkService * Add Error for DiscussionProxiesNetworkService * tmp * Use ProfileAssembly * Use Comment.IdType * Remove unused * Create VotesNetworkService * Inject VotesNetworkService * Set DiscussionsViewController * Update VoteValue comparison * Initial commit for DiscussionsView * Fetch & like & abuse comments * Make DiscussionsViewData immutable * Show more text for loading cells * Refactor rename DiscussionsViewData's vars * Update loading cells * Increment step discussions sount on create * Set Swift language version to 4.2 * Run swiftlint autocorrect * Refactor rename discussionsFetchingRepliesIds * Use StepsPersistenceService * Create DiscussionsTableViewDataSource * Display alert on error * Move SeparatorType to DiscussionsViewData * Refresh on appear
1 parent d071d1c commit 254139f

27 files changed

+1006
-1382
lines changed

.swift-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0
1+
4.2

Stepic.xcodeproj/project.pbxproj

Lines changed: 66 additions & 122 deletions
Large diffs are not rendered by default.

Stepic/CardsStepsViewController.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ class CardsStepsViewController: UIViewController, CardsStepsView, ControllerWith
101101
}
102102

103103
func presentDiscussions(stepId: Int, discussionProxyId: String) {
104-
let vc = DiscussionsViewController(nibName: "DiscussionsViewController", bundle: nil)
105-
vc.discussionProxyId = discussionProxyId
106-
vc.target = stepId
107-
navigationController?.pushViewController(vc, animated: true)
104+
let assembly = DiscussionsLegacyAssembly(
105+
discussionProxyID: discussionProxyId,
106+
stepID: stepId
107+
)
108+
self.push(module: assembly.makeModule())
108109
}
109110

110111
func updateProgress(rating: Int, prevMaxRating: Int, maxRating: Int, level: Int) {

Stepic/DeepLinkRouter.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,11 @@ final class DeepLinkRouter {
281281
}
282282

283283
if let discussionProxyId = step.discussionProxyId {
284-
let vc = DiscussionsViewController(nibName: "DiscussionsViewController", bundle: nil)
285-
vc.discussionProxyId = discussionProxyId
286-
vc.target = step.id
287-
vc.step = step
288-
completion(viewControllers + [vc])
284+
let assembly = DiscussionsLegacyAssembly(
285+
discussionProxyID: discussionProxyId,
286+
stepID: step.id
287+
)
288+
completion(viewControllers + [assembly.makeModule()])
289289
} else {
290290
completion([])
291291
}
@@ -317,11 +317,11 @@ final class DeepLinkRouter {
317317
}
318318

319319
if let discussionProxyId = step.discussionProxyId {
320-
let vc = DiscussionsViewController(nibName: "DiscussionsViewController", bundle: nil)
321-
vc.discussionProxyId = discussionProxyId
322-
vc.target = step.id
323-
vc.step = step
324-
completion(viewControllers + [vc])
320+
let assembly = DiscussionsLegacyAssembly(
321+
discussionProxyID: discussionProxyId,
322+
stepID: step.id
323+
)
324+
completion(viewControllers + [assembly.makeModule()])
325325
} else {
326326
completion([])
327327
}

Stepic/DiscussionAlertConstructor.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
final class DiscussionAlertConstructor {
1212
static func getCommentAlert(
13-
_ comment: Comment,
13+
comment: Comment,
1414
replyBlock: @escaping (() -> Void),
1515
likeBlock: @escaping (() -> Void),
1616
abuseBlock: @escaping (() -> Void),
@@ -39,19 +39,17 @@ final class DiscussionAlertConstructor {
3939
}))
4040

4141
if comment.userId != AuthInfo.shared.userId {
42-
let likeTitle: String = (comment.vote.value == VoteValue.Epic)
42+
let likeTitle: String = (comment.vote.value == .epic)
4343
? NSLocalizedString("Unlike", comment: "")
4444
: NSLocalizedString("Like", comment: "")
45-
alert.addAction(UIAlertAction(title: likeTitle, style: .default, handler: {
46-
_ in
45+
alert.addAction(UIAlertAction(title: likeTitle, style: .default, handler: { _ in
4746
likeBlock()
4847
}))
4948

50-
let abuseTitle: String = (comment.vote.value == VoteValue.Abuse)
49+
let abuseTitle: String = (comment.vote.value == .abuse)
5150
? NSLocalizedString("Unabuse", comment: "")
5251
: NSLocalizedString("Abuse", comment: "")
53-
alert.addAction(UIAlertAction(title: abuseTitle, style: .destructive, handler: {
54-
_ in
52+
alert.addAction(UIAlertAction(title: abuseTitle, style: .destructive, handler: { _ in
5553
abuseBlock()
5654
}))
5755
}

Stepic/DiscussionCellDelegate.swift

Lines changed: 0 additions & 13 deletions
This file was deleted.

Stepic/DiscussionTableViewCell.swift

Lines changed: 92 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -10,156 +10,143 @@ import UIKit
1010
import SDWebImage
1111
import SnapKit
1212

13-
protocol DiscussionTableViewCellDelegate: class {
14-
func didOpenProfile(for userWithId: Int)
15-
}
16-
17-
class DiscussionTableViewCell: UITableViewCell {
18-
weak var delegate: DiscussionTableViewCellDelegate?
19-
13+
final class DiscussionTableViewCell: UITableViewCell, Reusable, NibLoadable {
2014
@IBOutlet weak var userAvatarImageView: AvatarImageView!
21-
@IBOutlet weak var nameLabel: StepikLabel!
15+
@IBOutlet weak var userAvatarImageViewLeadingConstraint: NSLayoutConstraint!
2216

23-
@IBOutlet weak var badgeLabel: WiderLabel!
17+
@IBOutlet weak var commentLabel: StepikLabel!
18+
@IBOutlet weak var commentLabelLeadingConstraint: NSLayoutConstraint!
2419

2520
@IBOutlet weak var separatorView: UIView!
26-
@IBOutlet weak var timeLabel: StepikLabel!
27-
28-
@IBOutlet weak var labelLeadingConstraint: NSLayoutConstraint!
29-
30-
@IBOutlet weak var ImageLeadingConstraint: NSLayoutConstraint!
31-
32-
@IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
33-
@IBOutlet weak var separatorLeadingConstraint: NSLayoutConstraint!
21+
@IBOutlet weak var separatorViewHeightConstraint: NSLayoutConstraint!
22+
@IBOutlet weak var separatorViewLeadingConstraint: NSLayoutConstraint!
3423

24+
@IBOutlet weak var nameLabel: StepikLabel!
25+
@IBOutlet weak var badgeLabel: WiderLabel!
26+
@IBOutlet weak var timeLabel: StepikLabel!
3527
@IBOutlet weak var likesLabel: StepikLabel!
3628
@IBOutlet weak var likesImageView: UIImageView!
3729

38-
@IBOutlet weak var commentLabel: StepikLabel!
30+
var comment: Comment?
31+
32+
var onProfileButtonClick: ((Int) -> Void)?
3933

40-
var hasSeparator: Bool = false {
34+
private var hasSeparator: Bool = false {
4135
didSet {
42-
separatorView?.isHidden = !hasSeparator
36+
self.separatorView.isHidden = !self.hasSeparator
4337
}
4438
}
4539

46-
var separatorType: SeparatorType = .none {
40+
private var separatorType: DiscussionsViewData.SeparatorType = .none {
4741
didSet {
48-
switch separatorType {
42+
switch self.separatorType {
4943
case .none:
50-
hasSeparator = false
51-
separatorHeightConstraint.constant = 0
52-
break
44+
self.hasSeparator = false
45+
self.separatorViewHeightConstraint.constant = 0
5346
case .small:
54-
hasSeparator = true
55-
separatorHeightConstraint.constant = 0.5
56-
separatorLeadingConstraint.constant = 8
57-
break
47+
self.hasSeparator = true
48+
self.separatorViewHeightConstraint.constant = 0.5
49+
self.separatorViewLeadingConstraint.constant = 8
5850
case .big:
59-
hasSeparator = true
60-
separatorHeightConstraint.constant = 10
61-
separatorLeadingConstraint.constant = -8
62-
break
51+
self.hasSeparator = true
52+
self.separatorViewHeightConstraint.constant = 10
53+
self.separatorViewLeadingConstraint.constant = -8
6354
}
64-
updateConstraints()
55+
self.updateConstraints()
6556
}
6657
}
6758

68-
var comment: Comment?
69-
var heightUpdateBlock : (() -> Void)?
59+
override func awakeFromNib() {
60+
super.awakeFromNib()
61+
62+
self.badgeLabel.setRoundedCorners(cornerRadius: 10)
63+
64+
self.nameLabel?.isUserInteractionEnabled = true
65+
self.nameLabel?.addGestureRecognizer(
66+
UITapGestureRecognizer(target: self, action: #selector(self.actionUserTapped))
67+
)
68+
69+
self.userAvatarImageView?.isUserInteractionEnabled = true
70+
self.userAvatarImageView?.addGestureRecognizer(
71+
UITapGestureRecognizer(target: self, action: #selector(self.actionUserTapped))
72+
)
73+
}
74+
75+
override func prepareForReuse() {
76+
super.prepareForReuse()
77+
78+
self.comment = nil
79+
self.updateConstraints()
80+
}
81+
82+
override func updateConstraints() {
83+
super.updateConstraints()
84+
self.setLeadingConstraints(self.comment?.parentId == nil ? 0 : -40)
85+
}
86+
87+
func configure(viewData: DiscussionsViewData) {
88+
guard let comment = viewData.comment else {
89+
return
90+
}
7091

71-
func initWithComment(_ comment: Comment, separatorType: SeparatorType) {
7292
if let url = URL(string: comment.userInfo.avatarURL) {
73-
userAvatarImageView.set(with: url)
93+
self.userAvatarImageView.set(with: url)
7494
}
7595

76-
nameLabel.text = "\(comment.userInfo.firstName) \(comment.userInfo.lastName)"
96+
self.nameLabel.text = "\(comment.userInfo.firstName) \(comment.userInfo.lastName)"
7797
self.comment = comment
78-
self.separatorType = separatorType
79-
timeLabel.text = comment.time.getStepicFormatString(withTime: true)
80-
setLiked(comment.vote.value == .Epic, likesCount: comment.epicCount)
81-
loadLabel(comment.text)
98+
self.separatorType = viewData.separatorType
99+
self.timeLabel.text = comment.time.getStepicFormatString(withTime: true)
100+
self.setLiked(comment.vote.value == .epic, likesCount: comment.epicCount)
101+
self.commentLabel.setTextWithHTMLString(comment.text)
102+
82103
if comment.isDeleted {
83-
self.contentView.backgroundColor = UIColor.wrongQuizBackground
104+
self.contentView.backgroundColor = .wrongQuizBackground
84105
if comment.text == "" {
85-
loadLabel(NSLocalizedString("DeletedComment", comment: ""))
106+
self.commentLabel.text = NSLocalizedString("DeletedComment", comment: "")
86107
}
87108
} else {
88-
self.contentView.backgroundColor = UIColor.white
109+
self.contentView.backgroundColor = .white
89110
}
90111

91112
switch comment.userRole {
92-
case .Student:
93-
badgeLabel.text = ""
94-
badgeLabel.backgroundColor = UIColor.clear
95-
case .Teacher:
96-
badgeLabel.text = NSLocalizedString("CourseStaff", comment: "")
97-
badgeLabel.backgroundColor = UIColor.lightGray
98-
case .Staff:
99-
badgeLabel.text = NSLocalizedString("Staff", comment: "")
100-
badgeLabel.backgroundColor = UIColor.lightGray
113+
case .student:
114+
self.badgeLabel.text = ""
115+
self.badgeLabel.backgroundColor = .clear
116+
case .teacher:
117+
self.badgeLabel.text = NSLocalizedString("CourseStaff", comment: "")
118+
self.badgeLabel.backgroundColor = .lightGray
119+
case .staff:
120+
self.badgeLabel.text = NSLocalizedString("Staff", comment: "")
121+
self.badgeLabel.backgroundColor = .lightGray
101122
}
102123
}
103124

104-
fileprivate func loadLabel(_ htmlString: String) {
105-
commentLabel.setTextWithHTMLString(htmlString)
125+
private func setLiked(_ liked: Bool, likesCount: Int) {
126+
self.likesLabel.text = "\(likesCount)"
127+
if liked {
128+
self.likesImageView.image = Images.thumbsUp.filled
129+
} else {
130+
self.likesImageView.image = Images.thumbsUp.normal
131+
}
106132
}
107133

108-
fileprivate func setLeadingConstraints(_ constant: CGFloat) {
109-
ImageLeadingConstraint.constant = constant
110-
labelLeadingConstraint.constant = -constant
134+
private func setLeadingConstraints(_ constant: CGFloat) {
135+
self.userAvatarImageViewLeadingConstraint.constant = constant
136+
self.commentLabelLeadingConstraint.constant = -constant
137+
111138
switch self.separatorType {
112139
case .small:
113-
separatorLeadingConstraint.constant = -constant
114-
break
140+
self.separatorViewLeadingConstraint.constant = -constant
115141
default:
116142
break
117143
}
118144
}
119145

120-
func setLiked(_ liked: Bool, likesCount: Int) {
121-
likesLabel.text = "\(likesCount)"
122-
if liked {
123-
likesImageView.image = Images.thumbsUp.filled
124-
} else {
125-
likesImageView.image = Images.thumbsUp.normal
126-
}
127-
}
128-
129-
override func awakeFromNib() {
130-
super.awakeFromNib()
131-
badgeLabel.setRoundedCorners(cornerRadius: 10)
132-
133-
let tapActionNameLabel = UITapGestureRecognizer(target: self, action: #selector(self.actionUserTapped))
134-
nameLabel?.isUserInteractionEnabled = true
135-
nameLabel?.addGestureRecognizer(tapActionNameLabel)
136-
137-
let tapActionAvatarView = UITapGestureRecognizer(target: self, action: #selector(self.actionUserTapped))
138-
userAvatarImageView?.isUserInteractionEnabled = true
139-
userAvatarImageView?.addGestureRecognizer(tapActionAvatarView)
140-
}
141-
142-
@objc func actionUserTapped() {
143-
guard let userId = comment?.userInfo.id else {
144-
return
146+
@objc
147+
private func actionUserTapped() {
148+
if let userId = self.comment?.userInfo.id {
149+
self.onProfileButtonClick?(userId)
145150
}
146-
147-
delegate?.didOpenProfile(for: userId)
148-
}
149-
150-
override func prepareForReuse() {
151-
super.prepareForReuse()
152-
comment = nil
153-
updateConstraints()
154-
}
155-
156-
override func updateConstraints() {
157-
super.updateConstraints()
158-
setLeadingConstraints(comment?.parentId == nil ? 0 : -40)
159-
}
160-
161-
override func setSelected(_ selected: Bool, animated: Bool) {
162-
super.setSelected(selected, animated: animated)
163151
}
164-
165152
}

Stepic/DiscussionTableViewCell.xib

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" 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="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
33
<device id="retina4_7" orientation="portrait">
44
<adaptation id="fullscreen"/>
55
</device>
66
<dependencies>
77
<deployment identifier="iOS"/>
8-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
9-
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
8+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
109
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
1110
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1211
</dependencies>
@@ -63,7 +62,7 @@
6362
</constraints>
6463
</imageView>
6564
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="753" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0qt-gd-xNy" customClass="StepikLabel" customModule="Adaptive_1838" customModuleProvider="target">
66-
<rect key="frame" x="380" y="13" width="9" height="16"/>
65+
<rect key="frame" x="380" y="12.5" width="9" height="16"/>
6766
<fontDescription key="fontDescription" type="system" pointSize="13"/>
6867
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
6968
<nil key="highlightedColor"/>
@@ -114,18 +113,18 @@
114113
<viewLayoutGuide key="safeArea" id="A0U-wb-SKO"/>
115114
<inset key="separatorInset" minX="15" minY="0.0" maxX="0.0" maxY="0.0"/>
116115
<connections>
117-
<outlet property="ImageLeadingConstraint" destination="zeC-Ii-ThB" id="ZcW-0g-gNI"/>
118116
<outlet property="badgeLabel" destination="JBD-B0-dRF" id="xD5-za-CIg"/>
119117
<outlet property="commentLabel" destination="qtJ-hP-Joz" id="sc7-SB-dp1"/>
120-
<outlet property="labelLeadingConstraint" destination="eal-E1-aBI" id="15O-Re-2oa"/>
118+
<outlet property="commentLabelLeadingConstraint" destination="eal-E1-aBI" id="15O-Re-2oa"/>
121119
<outlet property="likesImageView" destination="eQf-K2-Thw" id="7Hh-xy-3WI"/>
122120
<outlet property="likesLabel" destination="0qt-gd-xNy" id="UQw-MR-Wd0"/>
123121
<outlet property="nameLabel" destination="6YZ-wn-n05" id="OxI-1P-viA"/>
124-
<outlet property="separatorHeightConstraint" destination="wgI-Pg-Mbo" id="epW-KA-daK"/>
125-
<outlet property="separatorLeadingConstraint" destination="EJ0-8Z-U7Z" id="X2X-wB-q8E"/>
126122
<outlet property="separatorView" destination="pV4-ue-5er" id="ZQA-fC-Y3W"/>
123+
<outlet property="separatorViewHeightConstraint" destination="wgI-Pg-Mbo" id="1BA-fY-gfC"/>
124+
<outlet property="separatorViewLeadingConstraint" destination="EJ0-8Z-U7Z" id="X2X-wB-q8E"/>
127125
<outlet property="timeLabel" destination="RmE-el-xJX" id="aU3-Xg-wIJ"/>
128126
<outlet property="userAvatarImageView" destination="IO2-jl-qQ3" id="FXP-ux-Uch"/>
127+
<outlet property="userAvatarImageViewLeadingConstraint" destination="zeC-Ii-ThB" id="ZcW-0g-gNI"/>
129128
</connections>
130129
<point key="canvasLocation" x="184.5" y="443"/>
131130
</tableViewCell>

0 commit comments

Comments
 (0)