From 3041f2cefda658e2389eebf91c2ceac4499a479b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktoras=20Laukevi=C4=8Dius?= Date: Wed, 20 Mar 2019 11:51:19 +0200 Subject: [PATCH 1/2] Preserve emojis order when adding * reactions order in app is defined by array in app (not received order from API) * reactions picker & UI list share the same data structure --- .../IssueCommentReactionViewModel.swift | 21 +++++++++++++-- .../Reactions/IssueReactionCell.swift | 11 +++++--- .../ReactionsMenuViewController.swift | 27 +++++++++---------- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift b/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift index 02c70dac4..f506dd24e 100644 --- a/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift +++ b/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift @@ -17,16 +17,33 @@ extension ReactionContent: Hashable { final class IssueCommentReactionViewModel: ListDiffable { + static let allReactions: [ReactionContent] = [ + .thumbsUp, + .thumbsDown, + .laugh, + .hooray, + .confused, + .heart, + .rocket, + .eyes + ] + let models: [ReactionViewModel] private let map: [ReactionContent: ReactionViewModel] private let flatState: String init(models: [ReactionViewModel]) { - self.models = models + let reactions = IssueCommentReactionViewModel.allReactions + let sortedModels = models.sorted { (m1, m2) -> Bool in + let m1Idx = reactions.firstIndex(of: m1.content) ?? 0 + let m2Idx = reactions.firstIndex(of: m2.content) ?? 0 + return m1Idx < m2Idx + } + self.models = sortedModels var map = [ReactionContent: ReactionViewModel]() var flatState = "" - for model in models { + for model in sortedModels { map[model.content] = model flatState += "\(model.content.rawValue)\(model.count)" } diff --git a/Classes/Issues/Comments/Reactions/IssueReactionCell.swift b/Classes/Issues/Comments/Reactions/IssueReactionCell.swift index 788a57d22..7b990b0d6 100644 --- a/Classes/Issues/Comments/Reactions/IssueReactionCell.swift +++ b/Classes/Issues/Comments/Reactions/IssueReactionCell.swift @@ -89,6 +89,7 @@ final class IssueReactionCell: UICollectionViewCell { accessibilityHint = isViewer ? NSLocalizedString("Tap to remove your reaction", comment: "") : NSLocalizedString("Tap to react with this emoji", comment: "") + restoreDisplay() } func popIn() { @@ -109,9 +110,7 @@ final class IssueReactionCell: UICollectionViewCell { // hack to prevent changing to "0" countLabel.text = "1" - countLabel.alpha = 1 - emojiLabel.transform = .identity - emojiLabel.alpha = 1 + restoreDisplay() UIView.animate(withDuration: 0.2, delay: 0, animations: { self.countLabel.alpha = 0 self.emojiLabel.transform = CGAffineTransform(scaleX: 0.3, y: 0.3) @@ -130,6 +129,12 @@ final class IssueReactionCell: UICollectionViewCell { // MARK: Private API + func restoreDisplay() { + countLabel.alpha = 1 + emojiLabel.transform = .identity + emojiLabel.alpha = 1 + } + @objc func showMenu(recognizer: UITapGestureRecognizer) { guard recognizer.state == .began, !detailText.isEmpty else { return } diff --git a/Classes/Issues/Comments/Reactions/ReactionsMenuViewController.swift b/Classes/Issues/Comments/Reactions/ReactionsMenuViewController.swift index e265f3421..1fcf8e5af 100644 --- a/Classes/Issues/Comments/Reactions/ReactionsMenuViewController.swift +++ b/Classes/Issues/Comments/Reactions/ReactionsMenuViewController.swift @@ -33,26 +33,25 @@ final class EmojiCell: UICollectionViewCell { } +private extension Array { + func split(toNumberOfChunks number: Int) -> [[Element]] { + let size = count / number + return (0 ..< number).map { + let from = $0 * size + let to = from + size + let isLast = ($0 == number - 1) + return Array(self[from ..< (isLast ? count : to)]) + } + } +} + final class ReactionsMenuViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { private let reuseIdentifier = "cell" private let size: CGFloat = 50 - private let sectionedReactions: [[ReactionContent]] = [ - [ - .thumbsUp, - .thumbsDown, - .laugh, - .hooray - ], - [ - .confused, - .heart, - .rocket, - .eyes - ] - ] + private let sectionedReactions = IssueCommentReactionViewModel.allReactions.split(toNumberOfChunks: 2) var selectedReaction: ReactionContent? { guard let item = collectionView?.indexPathsForSelectedItems?.first else { return nil } From 4d859f4c4c3a56c921429caeb1b665470d9e6efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktoras=20Laukevi=C4=8Dius?= Date: Fri, 7 Jun 2019 11:26:32 +0300 Subject: [PATCH 2/2] Tweak reactions sorting logic --- .../Comments/Reactions/IssueCommentReactionViewModel.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift b/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift index f506dd24e..31e29f292 100644 --- a/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift +++ b/Classes/Issues/Comments/Reactions/IssueCommentReactionViewModel.swift @@ -34,11 +34,10 @@ final class IssueCommentReactionViewModel: ListDiffable { init(models: [ReactionViewModel]) { let reactions = IssueCommentReactionViewModel.allReactions - let sortedModels = models.sorted { (m1, m2) -> Bool in - let m1Idx = reactions.firstIndex(of: m1.content) ?? 0 - let m2Idx = reactions.firstIndex(of: m2.content) ?? 0 - return m1Idx < m2Idx + let indexOfModel: (ReactionViewModel) -> Int = { + reactions.firstIndex(of: $0.content) ?? 0 } + let sortedModels = models.sorted { indexOfModel($0) < indexOfModel($1) } self.models = sortedModels var map = [ReactionContent: ReactionViewModel]()