From 5feb87f069b70d169ccb58778ca7a9f5e780227e Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 19 May 2022 17:10:53 +1000 Subject: [PATCH] ui: add interaction to reaction view --- .../ConversationVC+Interaction.swift | 26 +++++++++++++++---- .../Content Views/ReactionContainerView.swift | 17 +++++++++--- .../Content Views/ReactionView.swift | 6 ++--- .../Message Cells/MessageCell.swift | 2 ++ .../Message Cells/VisibleMessageCell.swift | 12 +++++++++ .../Messages/Signal/TSMessage.h | 3 ++- .../Messages/Signal/TSMessage.m | 12 ++++++++- 7 files changed, 64 insertions(+), 14 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 1a1614631..30e8dddaf 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -820,8 +820,21 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc } func react(_ viewItem: ConversationViewItem, with emoji: String) { - print("Ryan Test: \(emoji)") UserDefaults.standard.addNewRecentlyUsedEmoji(emoji) + react(viewItem, with: emoji, cancel: false) + } + + func quickReact(_ viewItem: ConversationViewItem, with emoji: String) { + print("Ryan Test: Quick react with \(emoji)") + react(viewItem, with: emoji) + } + + func cancelReact(_ viewItem: ConversationViewItem, for emoji: String) { + print("Ryan Test: Cancel react for \(emoji)") + react(viewItem, with: emoji, cancel: true) + } + + private func react(_ viewItem: ConversationViewItem, with emoji: String, cancel: Bool) { guard let message = viewItem.interaction as? TSMessage else { return } var authorId = getUserHexEncodedPublicKey() if let incomingMessage = message as? TSIncomingMessage { authorId = incomingMessage.authorId } @@ -832,11 +845,14 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc let visibleMessage = VisibleMessage() visibleMessage.sentTimestamp = sentTimestamp visibleMessage.reaction = .from(reactMessage) - visibleMessage.reaction?.kind = .react + visibleMessage.reaction?.kind = cancel ? .remove : .react Storage.write { transaction in - message.update(withReaction: reactMessage, transaction: transaction) - // TODO: send emoji react message -// MessageSender.send(<#T##message: Message##Message#>, in: thread, using: <#T##YapDatabaseReadWriteTransaction#>) + if cancel { + message.removeReaction(reactMessage, transaction: transaction) } + else { + message.addReaction(reactMessage, transaction: transaction) + } + // MessageSender.send(visibleMessage, in: thread, using: transaction) } } diff --git a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift index d8c768f4a..1c9bda6de 100644 --- a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift +++ b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift @@ -10,6 +10,8 @@ final class ReactionContainerView : UIView { private var showingAllReactions = false + var reactionViews: [ReactionView] = [] + // MARK: Lifecycle init() { super.init(frame: CGRect.zero) @@ -30,10 +32,8 @@ final class ReactionContainerView : UIView { } public func update(_ reactions: [(String, (Int, Bool))]) { - for subview in containerView.arrangedSubviews { - containerView.removeArrangedSubview(subview) - subview.removeFromSuperview() - } + prepareForUpdate() + let stackView = UIStackView() stackView.axis = .horizontal stackView.spacing = Values.smallSpacing @@ -53,6 +53,7 @@ final class ReactionContainerView : UIView { for reaction in displayedReactions { let reactionView = ReactionView(emoji: reaction.0, value: reaction.1) stackView.addArrangedSubview(reactionView) + reactionViews.append(reactionView) } if expandButtonReactions.count > 0 { let expandButton = ExpandingReactionButton(emojis: expandButtonReactions) @@ -60,6 +61,14 @@ final class ReactionContainerView : UIView { } containerView.addArrangedSubview(stackView) } + + private func prepareForUpdate() { + for subview in containerView.arrangedSubviews { + containerView.removeArrangedSubview(subview) + subview.removeFromSuperview() + } + reactionViews = [] + } } diff --git a/Session/Conversations/Message Cells/Content Views/ReactionView.swift b/Session/Conversations/Message Cells/Content Views/ReactionView.swift index 662dbff2b..d535d2cd5 100644 --- a/Session/Conversations/Message Cells/Content Views/ReactionView.swift +++ b/Session/Conversations/Message Cells/Content Views/ReactionView.swift @@ -1,9 +1,9 @@ import UIKit final class ReactionView : UIView { - private let emoji: String - private let number: Int - private let hasCurrentUser: Bool + let emoji: String + let number: Int + let hasCurrentUser: Bool // MARK: Settings private static let height: CGFloat = 22 diff --git a/Session/Conversations/Message Cells/MessageCell.swift b/Session/Conversations/Message Cells/MessageCell.swift index 9bc79bcfe..a059cb079 100644 --- a/Session/Conversations/Message Cells/MessageCell.swift +++ b/Session/Conversations/Message Cells/MessageCell.swift @@ -80,4 +80,6 @@ protocol MessageCellDelegate : AnyObject { func openURL(_ url: URL) func handleReplyButtonTapped(for viewItem: ConversationViewItem) func showUserDetails(for sessionID: String) + func quickReact(_ viewItem: ConversationViewItem, with emoji: String) + func cancelReact(_ viewItem: ConversationViewItem, for emoji: String) } diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index f3a7e45f8..8c75ac9fa 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -548,6 +548,18 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate { } else if replyButton.frame.contains(location) { UIImpactFeedbackGenerator(style: .heavy).impactOccurred() reply() + } else if reactionContainerView.frame.contains(location) { + let convertedLocation = reactionContainerView.convert(location, from: self) + for reactionView in reactionContainerView.reactionViews { + if reactionView.frame.contains(convertedLocation) { + if reactionView.hasCurrentUser { + delegate?.cancelReact(viewItem, for: reactionView.emoji) + } else { + delegate?.quickReact(viewItem, with: reactionView.emoji) + } + break + } + } } else { delegate?.handleViewItemTapped(viewItem, gestureRecognizer: gestureRecognizer) } diff --git a/SessionMessagingKit/Messages/Signal/TSMessage.h b/SessionMessagingKit/Messages/Signal/TSMessage.h index dc58ab759..951b42a4c 100644 --- a/SessionMessagingKit/Messages/Signal/TSMessage.h +++ b/SessionMessagingKit/Messages/Signal/TSMessage.h @@ -90,7 +90,8 @@ extern const NSUInteger kOversizeTextMessageSizeThreshold; - (void)updateCallMessageWithNewBody:(NSString *)newBody transaction:(YapDatabaseReadWriteTransaction *)transaction; -- (void)updateWithReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction; +- (void)addReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction; +- (void)removeReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction; @end diff --git a/SessionMessagingKit/Messages/Signal/TSMessage.m b/SessionMessagingKit/Messages/Signal/TSMessage.m index db112d305..7a8d4e845 100644 --- a/SessionMessagingKit/Messages/Signal/TSMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSMessage.m @@ -457,7 +457,7 @@ const NSUInteger kOversizeTextMessageSizeThreshold = 2 * 1024; }]; } -- (void)updateWithReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction +- (void)addReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction { if ([self isKindOfClass:[TSIncomingMessage class]] || [self isKindOfClass:[TSOutgoingMessage class]]) { [self applyChangeToSelfAndLatestCopy:transaction @@ -469,6 +469,16 @@ const NSUInteger kOversizeTextMessageSizeThreshold = 2 * 1024; } } +- (void)removeReaction:(SNReactMessage *)reaction transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + if ([self isKindOfClass:[TSIncomingMessage class]] || [self isKindOfClass:[TSOutgoingMessage class]]) { + [self applyChangeToSelfAndLatestCopy:transaction + changeBlock:^(TSMessage *message) { + [message.reactions removeObject:reaction]; + }]; + } +} + @end NS_ASSUME_NONNULL_END