refactor: use view model for reaction button

pull/638/head
Ryan Zhao 3 years ago
parent d83100e3a0
commit b6b99fac69

@ -21,7 +21,7 @@ final class ReactionContainerView : UIView {
private var showNumbers = true private var showNumbers = true
private var maxEmojisPerLine = isIPhone6OrSmaller ? 5 : 6 private var maxEmojisPerLine = isIPhone6OrSmaller ? 5 : 6
var reactions: [(EmojiWithSkinTones, (Int, Bool))] = [] var reactions: [ReactionViewModel] = []
var reactionViews: [ReactionButton] = [] var reactionViews: [ReactionButton] = []
var expandButton: ExpandingReactionButton? var expandButton: ExpandingReactionButton?
var collapseButton: UIStackView = { var collapseButton: UIStackView = {
@ -58,7 +58,7 @@ final class ReactionContainerView : UIView {
mainStackView.pin(to: self) 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.reactions = reactions
self.isOutgoingMessage = isOutgoingMessage self.isOutgoingMessage = isOutgoingMessage
self.showNumbers = showNumbers 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() let stackView = UIStackView()
stackView.axis = .horizontal stackView.axis = .horizontal
stackView.spacing = Values.smallSpacing stackView.spacing = Values.smallSpacing
@ -83,19 +83,19 @@ final class ReactionContainerView : UIView {
reactionContainerView.semanticContentAttribute = .unspecified reactionContainerView.semanticContentAttribute = .unspecified
} }
var displayedReactions: [(EmojiWithSkinTones, (Int, Bool))] var displayedReactions: [ReactionViewModel]
var expandButtonReactions: [EmojiWithSkinTones] var expandButtonReactions: [EmojiWithSkinTones]
if reactions.count > maxEmojisPerLine { if reactions.count > maxEmojisPerLine {
displayedReactions = Array(reactions[0...(maxEmojisPerLine - 3)]) 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 { } else {
displayedReactions = reactions displayedReactions = reactions
expandButtonReactions = [] expandButtonReactions = []
} }
for reaction in displayedReactions { 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) stackView.addArrangedSubview(reactionView)
reactionViews.append(reactionView) reactionViews.append(reactionView)
} }
@ -112,7 +112,7 @@ final class ReactionContainerView : UIView {
var reactions = self.reactions var reactions = self.reactions
var numberOfLines = 0 var numberOfLines = 0
while reactions.count > 0 { while reactions.count > 0 {
var line: [(EmojiWithSkinTones, (Int, Bool))] = [] var line: [ReactionViewModel] = []
while reactions.count > 0 && line.count < maxEmojisPerLine { while reactions.count > 0 && line.count < maxEmojisPerLine {
line.append(reactions.removeFirst()) line.append(reactions.removeFirst())
} }

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

@ -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() { override func layoutSubviews() {
@ -545,7 +545,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let convertedLocation = reactionContainerView.convert(location, from: self) let convertedLocation = reactionContainerView.convert(location, from: self)
for reactionView in reactionContainerView.reactionViews { for reactionView in reactionContainerView.reactionViews {
if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) { if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) {
delegate?.showReactionList(viewItem, selectedReaction: reactionView.emoji) delegate?.showReactionList(viewItem, selectedReaction: reactionView.viewModel.emoji)
break break
} }
} }
@ -569,10 +569,10 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
let convertedLocation = reactionContainerView.convert(location, from: self) let convertedLocation = reactionContainerView.convert(location, from: self)
for reactionView in reactionContainerView.reactionViews { for reactionView in reactionContainerView.reactionViews {
if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) { if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) {
if reactionView.showBorder { if reactionView.viewModel.showBorder {
delegate?.cancelReact(viewItem, for: reactionView.emoji) delegate?.cancelReact(viewItem, for: reactionView.viewModel.emoji)
} else { } else {
delegate?.quickReact(viewItem, with: reactionView.emoji) delegate?.quickReact(viewItem, with: reactionView.viewModel.emoji)
} }
return return
} }

Loading…
Cancel
Save