refactor: use view model for reaction button

This commit is contained in:
Ryan Zhao 2022-06-23 10:49:01 +10:00
parent d83100e3a0
commit b6b99fac69
3 changed files with 29 additions and 21 deletions

View File

@ -21,7 +21,7 @@ final class ReactionContainerView : UIView {
private var showNumbers = true
private var maxEmojisPerLine = isIPhone6OrSmaller ? 5 : 6
var reactions: [(EmojiWithSkinTones, (Int, Bool))] = []
var reactions: [ReactionViewModel] = []
var reactionViews: [ReactionButton] = []
var expandButton: ExpandingReactionButton?
var collapseButton: UIStackView = {
@ -58,7 +58,7 @@ final class ReactionContainerView : UIView {
mainStackView.pin(to: self)
}
public func update(_ reactions: [(EmojiWithSkinTones, (Int, Bool))], isOutgoingMessage: Bool, showNumbers: Bool) {
public func update(_ reactions: [ReactionViewModel], isOutgoingMessage: Bool, showNumbers: Bool) {
self.reactions = reactions
self.isOutgoingMessage = isOutgoingMessage
self.showNumbers = showNumbers
@ -70,7 +70,7 @@ final class ReactionContainerView : UIView {
}
}
private func updateCollapsedReactions(_ reactions: [(EmojiWithSkinTones, (Int, Bool))]) {
private func updateCollapsedReactions(_ reactions: [ReactionViewModel]) {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.spacing = Values.smallSpacing
@ -83,19 +83,19 @@ final class ReactionContainerView : UIView {
reactionContainerView.semanticContentAttribute = .unspecified
}
var displayedReactions: [(EmojiWithSkinTones, (Int, Bool))]
var displayedReactions: [ReactionViewModel]
var expandButtonReactions: [EmojiWithSkinTones]
if reactions.count > maxEmojisPerLine {
displayedReactions = Array(reactions[0...(maxEmojisPerLine - 3)])
expandButtonReactions = Array(reactions[(maxEmojisPerLine - 2)...maxEmojisPerLine]).map{ $0.0 }
expandButtonReactions = Array(reactions[(maxEmojisPerLine - 2)...maxEmojisPerLine]).map{ $0.emoji }
} else {
displayedReactions = reactions
expandButtonReactions = []
}
for reaction in displayedReactions {
let reactionView = ReactionButton(emoji: reaction.0, value: reaction.1.0, showBorder: reaction.1.1, showNumber: showNumbers)
let reactionView = ReactionButton(viewModel: reaction, showNumber: showNumbers)
stackView.addArrangedSubview(reactionView)
reactionViews.append(reactionView)
}
@ -112,7 +112,7 @@ final class ReactionContainerView : UIView {
var reactions = self.reactions
var numberOfLines = 0
while reactions.count > 0 {
var line: [(EmojiWithSkinTones, (Int, Bool))] = []
var line: [ReactionViewModel] = []
while reactions.count > 0 && line.count < maxEmojisPerLine {
line.append(reactions.removeFirst())
}

View File

@ -1,9 +1,19 @@
import UIKit
final class ReactionButton : UIView {
public struct ReactionViewModel: Hashable {
let emoji: EmojiWithSkinTones
let number: Int
let showBorder: Bool
init(emoji: EmojiWithSkinTones, value: Int, showBorder: Bool) {
self.emoji = emoji
self.number = value
self.showBorder = showBorder
}
}
final class ReactionButton: UIView {
let viewModel: ReactionViewModel
let showNumber: Bool
// MARK: Settings
@ -13,10 +23,8 @@ final class ReactionButton : UIView {
private var spacing: CGFloat = Values.verySmallSpacing
// MARK: Lifecycle
init(emoji: EmojiWithSkinTones, value: Int, showBorder: Bool = false, showNumber: Bool = true) {
self.emoji = emoji
self.number = value
self.showBorder = showBorder
init(viewModel: ReactionViewModel, showNumber: Bool = true) {
self.viewModel = viewModel
self.showNumber = showNumber
super.init(frame: CGRect.zero)
setUpViewHierarchy()
@ -32,7 +40,7 @@ final class ReactionButton : UIView {
private func setUpViewHierarchy() {
let emojiLabel = UILabel()
emojiLabel.text = emoji.rawValue
emojiLabel.text = viewModel.emoji.rawValue
emojiLabel.font = .systemFont(ofSize: fontSize)
let stackView = UIStackView(arrangedSubviews: [ emojiLabel ])
@ -48,13 +56,13 @@ final class ReactionButton : UIView {
backgroundColor = Colors.receivedMessageBackground
layer.cornerRadius = self.height / 2
if showBorder {
if viewModel.showBorder {
self.addBorder(with: Colors.accent)
}
if showNumber || self.number > 1 {
if showNumber || viewModel.number > 1 {
let numberLabel = UILabel()
numberLabel.text = self.number < 1000 ? "\(number)" : String(format: "%.1f", Float(number) / 1000) + "k"
numberLabel.text = viewModel.number < 1000 ? "\(viewModel.number)" : String(format: "%.1f", Float(viewModel.number) / 1000) + "k"
numberLabel.font = .systemFont(ofSize: fontSize)
numberLabel.textColor = Colors.text
stackView.addArrangedSubview(numberLabel)

View File

@ -468,7 +468,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
}
}
}
reactionContainerView.update(reactions.orderedItems, isOutgoingMessage: direction == .outgoing, showNumbers: thread!.isGroupThread())
reactionContainerView.update(reactions.orderedItems.map { ReactionViewModel(emoji: $0.0, value: $0.1.0, showBorder:$0.1.1 )}, isOutgoingMessage: direction == .outgoing, showNumbers: thread!.isGroupThread())
}
override func layoutSubviews() {
@ -545,7 +545,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let convertedLocation = reactionContainerView.convert(location, from: self)
for reactionView in reactionContainerView.reactionViews {
if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) {
delegate?.showReactionList(viewItem, selectedReaction: reactionView.emoji)
delegate?.showReactionList(viewItem, selectedReaction: reactionView.viewModel.emoji)
break
}
}
@ -569,10 +569,10 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let convertedLocation = reactionContainerView.convert(location, from: self)
for reactionView in reactionContainerView.reactionViews {
if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) {
if reactionView.showBorder {
delegate?.cancelReact(viewItem, for: reactionView.emoji)
if reactionView.viewModel.showBorder {
delegate?.cancelReact(viewItem, for: reactionView.viewModel.emoji)
} else {
delegate?.quickReact(viewItem, with: reactionView.emoji)
delegate?.quickReact(viewItem, with: reactionView.viewModel.emoji)
}
return
}