diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 5271276e5..98817bc8e 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -75,6 +75,8 @@ 32891D712264DF7B00C82226 /* DeviceVerificationVerifiedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32891D6F2264DF7B00C82226 /* DeviceVerificationVerifiedViewController.swift */; }; 32891D75226728EE00C82226 /* DeviceVerificationDataLoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32891D73226728EE00C82226 /* DeviceVerificationDataLoadingViewController.swift */; }; 32891D76226728EF00C82226 /* DeviceVerificationDataLoadingViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 32891D74226728EE00C82226 /* DeviceVerificationDataLoadingViewController.storyboard */; }; + 329E746622CD02EA006F9797 /* BubbleReactionActionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 329E746422CD02EA006F9797 /* BubbleReactionActionViewCell.xib */; }; + 329E746722CD02EA006F9797 /* BubbleReactionActionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 329E746522CD02EA006F9797 /* BubbleReactionActionViewCell.swift */; }; 32A6001622C661100042C1D9 /* EditHistoryViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A6000D22C661100042C1D9 /* EditHistoryViewState.swift */; }; 32A6001722C661100042C1D9 /* EditHistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A6000E22C661100042C1D9 /* EditHistoryViewController.swift */; }; 32A6001822C661100042C1D9 /* EditHistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A6000F22C661100042C1D9 /* EditHistoryViewModel.swift */; }; @@ -617,6 +619,8 @@ 32891D6F2264DF7B00C82226 /* DeviceVerificationVerifiedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifiedViewController.swift; sourceTree = ""; }; 32891D73226728EE00C82226 /* DeviceVerificationDataLoadingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationDataLoadingViewController.swift; sourceTree = ""; }; 32891D74226728EE00C82226 /* DeviceVerificationDataLoadingViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DeviceVerificationDataLoadingViewController.storyboard; sourceTree = ""; }; + 329E746422CD02EA006F9797 /* BubbleReactionActionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BubbleReactionActionViewCell.xib; sourceTree = ""; }; + 329E746522CD02EA006F9797 /* BubbleReactionActionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleReactionActionViewCell.swift; sourceTree = ""; }; 32A6000D22C661100042C1D9 /* EditHistoryViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewState.swift; sourceTree = ""; }; 32A6000E22C661100042C1D9 /* EditHistoryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewController.swift; sourceTree = ""; }; 32A6000F22C661100042C1D9 /* EditHistoryViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewModel.swift; sourceTree = ""; }; @@ -2001,6 +2005,8 @@ B1963B24228F1C4800CBA17F /* BubbleReactions */ = { isa = PBXGroup; children = ( + 329E746522CD02EA006F9797 /* BubbleReactionActionViewCell.swift */, + 329E746422CD02EA006F9797 /* BubbleReactionActionViewCell.xib */, B1963B31228F1C6B00CBA17F /* BubbleReactionsViewModelType.swift */, B1963B27228F1C4800CBA17F /* BubbleReactionsViewModel.swift */, B1963B25228F1C4800CBA17F /* BubbleReactionsView.swift */, @@ -3607,6 +3613,7 @@ B1B5574320EE6C4D00210D55 /* CallViewController.xib in Resources */, F083BDEA1E7009ED00A9B29C /* ringback.mp3 in Resources */, F083BDF21E7009ED00A9B29C /* GoogleService-Info.plist in Resources */, + 329E746622CD02EA006F9797 /* BubbleReactionActionViewCell.xib in Resources */, B1B558E320EF768F00210D55 /* RoomEmptyBubbleCell.xib in Resources */, B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */, B1B5590420EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.xib in Resources */, @@ -4098,6 +4105,7 @@ 32A6001A22C661100042C1D9 /* EditHistoryCoordinator.swift in Sources */, F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */, B1B558E620EF768F00210D55 /* RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, + 329E746722CD02EA006F9797 /* BubbleReactionActionViewCell.swift in Sources */, B1098BFB21ECFE65000DDA48 /* KeyBackupSetupCoordinatorType.swift in Sources */, B1098BF721ECFE65000DDA48 /* PasswordStrength.swift in Sources */, 324A2052225FC571004FE8B0 /* DeviceVerificationIncomingViewAction.swift in Sources */, diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 2a920ef5c..2ccf5624d 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -280,10 +280,8 @@ "room_event_action_view_encryption" = "Encryption Information"; "room_event_action_reply" = "Reply"; "room_event_action_edit" = "Edit"; -"room_event_action_reaction_agree" = "Agree %@"; -"room_event_action_reaction_disagree" = "Disagree %@"; -"room_event_action_reaction_like" = "Like %@"; -"room_event_action_reaction_dislike" = "Dislike %@"; +"room_event_action_reaction_show_all" = "Show all"; +"room_event_action_reaction_show_less" = "Show less"; "room_warning_about_encryption" = "End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption."; "room_event_failed_to_send" = "Failed to send"; "room_action_send_photo_or_video" = "Send photo or video"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 181d63de0..73988e0e6 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1722,21 +1722,13 @@ internal enum VectorL10n { internal static var roomEventActionQuote: String { return VectorL10n.tr("Vector", "room_event_action_quote") } - /// Agree %@ - internal static func roomEventActionReactionAgree(_ p1: String) -> String { - return VectorL10n.tr("Vector", "room_event_action_reaction_agree", p1) + /// Show all + internal static var roomEventActionReactionShowAll: String { + return VectorL10n.tr("Vector", "room_event_action_reaction_show_all") } - /// Disagree %@ - internal static func roomEventActionReactionDisagree(_ p1: String) -> String { - return VectorL10n.tr("Vector", "room_event_action_reaction_disagree", p1) - } - /// Dislike %@ - internal static func roomEventActionReactionDislike(_ p1: String) -> String { - return VectorL10n.tr("Vector", "room_event_action_reaction_dislike", p1) - } - /// Like %@ - internal static func roomEventActionReactionLike(_ p1: String) -> String { - return VectorL10n.tr("Vector", "room_event_action_reaction_like", p1) + /// Show less + internal static var roomEventActionReactionShowLess: String { + return VectorL10n.tr("Vector", "room_event_action_reaction_show_less") } /// Remove internal static var roomEventActionRedact: String { diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.swift b/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.swift new file mode 100644 index 000000000..5fbe5de8a --- /dev/null +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.swift @@ -0,0 +1,68 @@ +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import UIKit +import Reusable + +final class BubbleReactionActionViewCell: UICollectionViewCell, NibReusable, Themable { + + // MARK: - Constants + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var actionLabel: UILabel! + + // MARK: Private + + private var theme: Theme? + + // MARK: Public + + // MARK: - Life cycle + + override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { + if #available(iOS 12.0, *) { + /* + On iOS 12, there are issues with self-sizing cells as described in Apple release notes (https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes) : + "You might encounter issues with systemLayoutSizeFitting(_:) when using a UICollectionViewCell subclass that requires updateConstraints(). + (42138227) — Workaround: Don't call the cell's setNeedsUpdateConstraints() method unless you need to support live constraint changes. + If you need to support live constraint changes, call updateConstraintsIfNeeded() before calling systemLayoutSizeFitting(_:)." + */ + self.updateConstraintsIfNeeded() + } + return super.preferredLayoutAttributesFitting(layoutAttributes) + } + + // MARK: - Public + + func fill(actionString: String) { + self.actionLabel.text = actionString + self.updateViews() + } + + func update(theme: Theme) { + self.theme = theme + self.updateViews() + } + + // MARK: - Private + + private func updateViews() { + self.actionLabel.textColor = self.theme?.tintColor + } +} diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.xib b/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.xib new file mode 100644 index 000000000..fa3e5bdb7 --- /dev/null +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift b/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift index 33eaf486c..a3238b809 100644 --- a/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift @@ -38,6 +38,7 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable { // MARK: Private private var reactionsViewData: [BubbleReactionViewData] = [] + private var showAllButtonState: BubbleReactionsViewState.ShowAllButtonState = .none private var theme: Theme? // MARK: Public @@ -65,6 +66,7 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable { } self.collectionView.register(cellType: BubbleReactionViewCell.self) + self.collectionView.register(cellType: BubbleReactionActionViewCell.self) self.collectionView.reloadData() } @@ -90,31 +92,64 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable { self.theme = theme self.collectionView.reloadData() } + + // MARK: - Private - func fill(reactionsViewData: [BubbleReactionViewData]) { + private func fill(reactionsViewData: [BubbleReactionViewData], showAllButtonState: BubbleReactionsViewState.ShowAllButtonState) { self.reactionsViewData = reactionsViewData + self.showAllButtonState = showAllButtonState self.collectionView.reloadData() } + + private func actionButtonString() -> String { + let actionString: String + switch self.showAllButtonState { + case .showAll: + actionString = VectorL10n.roomEventActionReactionShowAll + case .showLess: + actionString = VectorL10n.roomEventActionReactionShowLess + case .none: + actionString = "" + } + + return actionString + } } // MARK: - UICollectionViewDataSource extension BubbleReactionsView: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return self.reactionsViewData.count + // "Show all" or "Show less" is a cell in the same section as reactions cells + let additionalItems = self.showAllButtonState == .none ? 0 : 1 + + return self.reactionsViewData.count + additionalItems } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell: BubbleReactionViewCell = collectionView.dequeueReusableCell(for: indexPath) - - if let theme = self.theme { - cell.update(theme: theme) + if indexPath.row < self.reactionsViewData.count { + let cell: BubbleReactionViewCell = collectionView.dequeueReusableCell(for: indexPath) + + if let theme = self.theme { + cell.update(theme: theme) + } + + let viewData = self.reactionsViewData[indexPath.row] + cell.fill(viewData: viewData) + + return cell + } else { + let cell: BubbleReactionActionViewCell = collectionView.dequeueReusableCell(for: indexPath) + + if let theme = self.theme { + cell.update(theme: theme) + } + + let actionString = self.actionButtonString() + cell.fill(actionString: actionString) + + return cell } - - let viewData = self.reactionsViewData[indexPath.row] - cell.fill(viewData: viewData) - - return cell } } @@ -122,7 +157,18 @@ extension BubbleReactionsView: UICollectionViewDataSource { extension BubbleReactionsView: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - self.viewModel?.process(viewAction: .tapReaction(index: indexPath.row)) + if indexPath.row < self.reactionsViewData.count { + self.viewModel?.process(viewAction: .tapReaction(index: indexPath.row)) + } else { + switch self.showAllButtonState { + case .showAll: + self.viewModel?.process(viewAction: .tapShowAction(action: .showAll)) + case .showLess: + self.viewModel?.process(viewAction: .tapShowAction(action: .showLess)) + case .none: + break + } + } } } @@ -131,8 +177,8 @@ extension BubbleReactionsView: BubbleReactionsViewModelViewDelegate { func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didUpdateViewState viewState: BubbleReactionsViewState) { switch viewState { - case .loaded(reactionsViewData: let reactionsViewData): - self.fill(reactionsViewData: reactionsViewData) + case .loaded(reactionsViewData: let reactionsViewData, showAllButtonState: let showAllButtonState): + self.fill(reactionsViewData: reactionsViewData, showAllButtonState: showAllButtonState) } } } diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift index 339b00987..1a79b6edb 100644 --- a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift @@ -17,14 +17,20 @@ import Foundation @objc final class BubbleReactionsViewModel: NSObject, BubbleReactionsViewModelType { - + + // MARK: - Constants + + private enum Constants { + static let maxItemsWhenLimited: Int = 8 + } + // MARK: - Properties // MARK: Private private let aggregatedReactions: MXAggregatedReactions - private let reactionsViewData: [BubbleReactionViewData] private let eventId: String + private let showAll: Bool // MARK: Public @@ -34,13 +40,11 @@ import Foundation // MARK: - Setup @objc init(aggregatedReactions: MXAggregatedReactions, - eventId: String) { + eventId: String, + showAll: Bool) { self.aggregatedReactions = aggregatedReactions self.eventId = eventId - - self.reactionsViewData = aggregatedReactions.reactions.map { (reactionCount) -> BubbleReactionViewData in - return BubbleReactionViewData(emoji: reactionCount.reaction, countString: "\(reactionCount.count)", isCurrentUserReacted: reactionCount.myUserHasReacted) - } + self.showAll = showAll } // MARK: - Public @@ -48,7 +52,7 @@ import Foundation func process(viewAction: BubbleReactionsViewAction) { switch viewAction { case .loadData: - self.viewDelegate?.bubbleReactionsViewModel(self, didUpdateViewState: .loaded(reactionsViewData: self.reactionsViewData)) + self.loadData() case .tapReaction(let index): guard index < self.aggregatedReactions.reactions.count else { return @@ -61,6 +65,31 @@ import Foundation } case .addNewReaction: break + case .tapShowAction(.showAll): + self.viewModelDelegate?.bubbleReactionsViewModel(self, didShowAllTappedForEventId: self.eventId) + case .tapShowAction(.showLess): + self.viewModelDelegate?.bubbleReactionsViewModel(self, didShowLessTappedForEventId: self.eventId) } } + + func loadData() { + var reactions = self.aggregatedReactions.reactions + var showAllButtonState: BubbleReactionsViewState.ShowAllButtonState = .none + + // Limit displayed reactions if required + if reactions.count > Constants.maxItemsWhenLimited { + if self.showAll == true { + showAllButtonState = .showLess + } else { + reactions = Array(reactions[0.. BubbleReactionViewData in + return BubbleReactionViewData(emoji: reactionCount.reaction, countString: "\(reactionCount.count)", isCurrentUserReacted: reactionCount.myUserHasReacted) + } + + self.viewDelegate?.bubbleReactionsViewModel(self, didUpdateViewState: .loaded(reactionsViewData: reactionsViewData, showAllButtonState: showAllButtonState)) + } } diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift index 04a30726a..3496854df 100644 --- a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift @@ -20,15 +20,29 @@ enum BubbleReactionsViewAction { case loadData case tapReaction(index: Int) case addNewReaction + case tapShowAction(action: ShowAction) + + enum ShowAction { + case showAll + case showLess + } } enum BubbleReactionsViewState { - case loaded(reactionsViewData: [BubbleReactionViewData]) + case loaded(reactionsViewData: [BubbleReactionViewData], showAllButtonState: ShowAllButtonState) + + enum ShowAllButtonState { + case none + case showAll + case showLess + } } @objc protocol BubbleReactionsViewModelDelegate: class { func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didAddReaction reactionCount: MXReactionCount, forEventId eventId: String) func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didRemoveReaction reactionCount: MXReactionCount, forEventId eventId: String) + func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didShowAllTappedForEventId eventId: String) + func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didShowLessTappedForEventId eventId: String) } protocol BubbleReactionsViewModelViewDelegate: class { diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.h b/Riot/Modules/Room/CellData/RoomBubbleCellData.h index a8317df00..e03035abb 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.h +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.h @@ -80,4 +80,10 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag) */ - (void)updateAdditionalContentHeightIfNeeded; + +#pragma mark - Show all reactions + +- (BOOL)showAllReactionsForEvent:(NSString*)eventId; +- (void)setShowAllReactions:(BOOL)showAllReactions forEvent:(NSString*)eventId; + @end diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 9a0d8b8fe..44f219b2f 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -32,6 +32,9 @@ static NSAttributedString *timestampVerticalWhitespace = nil; @property(nonatomic, readwrite) CGFloat additionalContentHeight; @property(nonatomic) BOOL shouldUpdateAdditionalContentHeight; +// Flags to "Show All" reactions for an event +@property(nonatomic) NSMutableSet *eventsToShowAllReactions; + @end @implementation RoomBubbleCellData @@ -43,6 +46,16 @@ static NSAttributedString *timestampVerticalWhitespace = nil; #pragma mark - Override MXKRoomBubbleCellData +- (instancetype)init +{ + self = [super init]; + if (self) + { + _eventsToShowAllReactions = [NSMutableSet set]; + } + return self; +} + - (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource2 { self = [super initWithEvent:event andRoomState:roomState andRoomDataSource:roomDataSource2]; @@ -368,9 +381,11 @@ static NSAttributedString *timestampVerticalWhitespace = nil; dispatch_once(&onceToken, ^{ bubbleReactionsView = [BubbleReactionsView new]; }); + + BOOL showAllReactions = [self.eventsToShowAllReactions containsObject:eventId]; bubbleReactionsView.frame = CGRectMake(0, 0, bubbleReactionsViewWidth, 1.0); - BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId]; + BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId showAll:showAllReactions]; bubbleReactionsView.viewModel = viemModel; [bubbleReactionsView setNeedsLayout]; [bubbleReactionsView layoutIfNeeded]; @@ -455,9 +470,11 @@ static NSAttributedString *timestampVerticalWhitespace = nil; dispatch_once(&onceToken, ^{ bubbleReactionsView = [BubbleReactionsView new]; }); + + BOOL showAllReactions = [self.eventsToShowAllReactions containsObject:eventId]; bubbleReactionsView.frame = CGRectMake(0, 0, bubbleReactionsViewWidth, 1.0); - BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId]; + BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId showAll:showAllReactions]; bubbleReactionsView.viewModel = viemModel; [bubbleReactionsView setNeedsLayout]; [bubbleReactionsView layoutIfNeeded]; @@ -636,4 +653,24 @@ static NSAttributedString *timestampVerticalWhitespace = nil; return [super addEvent:event andRoomState:roomState]; } + +#pragma mark - Show all reactions + +- (BOOL)showAllReactionsForEvent:(NSString*)eventId +{ + return [self.eventsToShowAllReactions containsObject:eventId]; +} + +- (void)setShowAllReactions:(BOOL)showAllReactions forEvent:(NSString*)eventId +{ + if (showAllReactions) + { + [self.eventsToShowAllReactions addObject:eventId]; + } + else + { + [self.eventsToShowAllReactions removeObject:eventId]; + } +} + @end diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index c7b642fb6..7282bd4eb 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -244,7 +244,10 @@ if (reactions && !isCollapsableCellCollapsed) { - BubbleReactionsViewModel *bubbleReactionsViewModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:reactions eventId:componentEventId]; + BOOL showAllReactions = [cellData showAllReactionsForEvent:componentEventId]; + BubbleReactionsViewModel *bubbleReactionsViewModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:reactions + eventId:componentEventId + showAll:showAllReactions]; reactionsView = [BubbleReactionsView new]; reactionsView.viewModel = bubbleReactionsViewModel; @@ -572,4 +575,28 @@ }]; } +- (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didShowAllTappedForEventId:(NSString * _Nonnull)eventId +{ + [self setShowAllReactions:YES forEvent:eventId]; +} + +- (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didShowLessTappedForEventId:(NSString * _Nonnull)eventId +{ + [self setShowAllReactions:NO forEvent:eventId]; +} + +- (void)setShowAllReactions:(BOOL)showAllReactions forEvent:(NSString*)eventId +{ + id cellData = [self cellDataOfEventWithEventId:eventId]; + if ([cellData isKindOfClass:[RoomBubbleCellData class]]) + { + RoomBubbleCellData *roomBubbleCellData = (RoomBubbleCellData*)cellData; + + [roomBubbleCellData setShowAllReactions:showAllReactions forEvent:eventId]; + [self updateCellDataReactions:roomBubbleCellData forEventId:eventId]; + + [self.delegate dataSource:self didCellChange:nil]; + } +} + @end