expand & collapse emoji reacts

pull/638/head
ryanzhao 2 years ago
parent 38665e6c33
commit 947869ef4c

@ -762,6 +762,13 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
return UITableView.automaticDimension return UITableView.automaticDimension
} }
func needsLayout() {
UIView.setAnimationsEnabled(false)
messagesTableView.beginUpdates()
messagesTableView.endUpdates()
UIView.setAnimationsEnabled(true)
}
func getMediaCache() -> NSCache<NSString, AnyObject> { func getMediaCache() -> NSCache<NSString, AnyObject> {
return mediaCache return mediaCache
} }

@ -337,7 +337,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
inputTextView.resignFirstResponder() inputTextView.resignFirstResponder()
} }
func handleLongPress() { func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
// Not relevant in this case // Not relevant in this case
} }

@ -1,18 +1,40 @@
final class ReactionContainerView : UIView { final class ReactionContainerView : UIView {
private lazy var containerView: UIStackView = { private lazy var mainStackView: UIStackView = {
let result = UIStackView() let result = UIStackView(arrangedSubviews: [ reactionContainerView ])
result.axis = .vertical result.axis = .vertical
result.spacing = Values.smallSpacing result.spacing = Values.smallSpacing
result.alignment = .center result.alignment = .center
return result return result
}() }()
private lazy var reactionContainerView: UIStackView = {
let result = UIStackView()
result.axis = .vertical
result.spacing = Values.smallSpacing
result.alignment = .leading
return result
}()
private var showingAllReactions = false private var showingAllReactions = false
var reactions: [(String, (Int, Bool))] = [] var reactions: [(String, (Int, Bool))] = []
var reactionViews: [ReactionView] = [] var reactionViews: [ReactionView] = []
var expandButton: ExpandingReactionButton? var expandButton: ExpandingReactionButton?
var collapseButton: UIStackView = {
let arrow = UIImageView(image: UIImage(named: "ic_chevron_up")?.resizedImage(to: CGSize(width: 15, height: 13))?.withRenderingMode(.alwaysTemplate))
arrow.tintColor = Colors.text
let textLabel = UILabel()
textLabel.text = "Show less"
textLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
textLabel.textColor = Colors.text
let result = UIStackView(arrangedSubviews: [ UIView.hStretchingSpacer(), arrow, textLabel, UIView.hStretchingSpacer() ])
result.spacing = Values.verySmallSpacing
result.alignment = .center
return result
}()
// MARK: Lifecycle // MARK: Lifecycle
init() { init() {
@ -29,14 +51,21 @@ final class ReactionContainerView : UIView {
} }
private func setUpViewHierarchy() { private func setUpViewHierarchy() {
addSubview(containerView) addSubview(mainStackView)
containerView.pin(to: self) mainStackView.pin(to: self)
} }
public func update(_ reactions: [(String, (Int, Bool))]) { public func update(_ reactions: [(String, (Int, Bool))]) {
self.reactions = reactions self.reactions = reactions
prepareForUpdate() prepareForUpdate()
if showingAllReactions {
updateAllReactions()
} else {
updateCollapsedReactions(reactions)
}
}
private func updateCollapsedReactions(_ reactions: [(String, (Int, Bool))]) {
let stackView = UIStackView() let stackView = UIStackView()
stackView.axis = .horizontal stackView.axis = .horizontal
stackView.spacing = Values.smallSpacing stackView.spacing = Values.smallSpacing
@ -64,14 +93,28 @@ final class ReactionContainerView : UIView {
} else { } else {
expandButton = nil expandButton = nil
} }
containerView.addArrangedSubview(stackView) reactionContainerView.addArrangedSubview(stackView)
}
private func updateAllReactions() {
var reactions = self.reactions
while reactions.count > 0 {
var line: [(String, (Int, Bool))] = []
while reactions.count > 0 && line.count < 5 {
line.append(reactions.removeFirst())
}
updateCollapsedReactions(line)
}
mainStackView.addArrangedSubview(collapseButton)
} }
private func prepareForUpdate() { private func prepareForUpdate() {
for subview in containerView.arrangedSubviews { for subview in reactionContainerView.arrangedSubviews {
containerView.removeArrangedSubview(subview) reactionContainerView.removeArrangedSubview(subview)
subview.removeFromSuperview() subview.removeFromSuperview()
} }
mainStackView.removeArrangedSubview(collapseButton)
collapseButton.removeFromSuperview()
reactionViews = [] reactionViews = []
} }
@ -80,6 +123,12 @@ final class ReactionContainerView : UIView {
showingAllReactions = true showingAllReactions = true
update(reactions) update(reactions)
} }
public func showLessEmojis() {
guard showingAllReactions else { return }
showingAllReactions = false
update(reactions)
}
} }

@ -82,4 +82,5 @@ protocol MessageCellDelegate : AnyObject {
func showUserDetails(for sessionID: String) func showUserDetails(for sessionID: String)
func quickReact(_ viewItem: ConversationViewItem, with emoji: String) func quickReact(_ viewItem: ConversationViewItem, with emoji: String)
func cancelReact(_ viewItem: ConversationViewItem, for emoji: String) func cancelReact(_ viewItem: ConversationViewItem, for emoji: String)
func needsLayout()
} }

@ -533,10 +533,22 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
} }
} }
@objc func handleLongPress() { @objc func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
guard let viewItem = viewItem else { return } guard let viewItem = viewItem else { return }
let location = gestureRecognizer.location(in: self)
if reactionContainerView.frame.contains(location) {
let convertedLocation = reactionContainerView.convert(location, from: self)
for reactionView in reactionContainerView.reactionViews {
if reactionView.frame.contains(convertedLocation) {
// TODO: Show react list
print("Ryan Test: long press on emoji.")
break
}
}
} else {
delegate?.handleViewItemLongPressed(viewItem) delegate?.handleViewItemLongPressed(viewItem)
} }
}
@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) { @objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard let viewItem = viewItem else { return } guard let viewItem = viewItem else { return }
@ -561,8 +573,12 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate {
} }
} }
if let expandButton = reactionContainerView.expandButton, expandButton.frame.contains(convertedLocation) { if let expandButton = reactionContainerView.expandButton, expandButton.frame.contains(convertedLocation) {
// TODO: show all emojis reactionContainerView.showAllEmojis()
reactionContainerView. delegate?.needsLayout()
}
if reactionContainerView.collapseButton.frame.contains(convertedLocation) {
reactionContainerView.showLessEmojis()
delegate?.needsLayout()
} }
} else { } else {
delegate?.handleViewItemTapped(viewItem, gestureRecognizer: gestureRecognizer) delegate?.handleViewItemTapped(viewItem, gestureRecognizer: gestureRecognizer)

@ -34,8 +34,8 @@ final class BodyTextView : UITextView {
addGestureRecognizer(doubleTapGestureRecognizer) addGestureRecognizer(doubleTapGestureRecognizer)
} }
@objc private func handleLongPress() { @objc private func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
snDelegate.handleLongPress() snDelegate.handleLongPress(gestureRecognizer)
} }
@objc private func handleDoubleTap() { @objc private func handleDoubleTap() {
@ -45,5 +45,5 @@ final class BodyTextView : UITextView {
protocol BodyTextViewDelegate { protocol BodyTextViewDelegate {
func handleLongPress() func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer)
} }

Loading…
Cancel
Save