Merge pull request #2549 from vector-im/riot_2510

Reactions: Show at most 8 reactions
This commit is contained in:
manuroe
2019-07-04 14:09:24 +02:00
committed by GitHub
11 changed files with 325 additions and 44 deletions
+8
View File
@@ -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 = "<group>"; };
32891D73226728EE00C82226 /* DeviceVerificationDataLoadingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationDataLoadingViewController.swift; sourceTree = "<group>"; };
32891D74226728EE00C82226 /* DeviceVerificationDataLoadingViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DeviceVerificationDataLoadingViewController.storyboard; sourceTree = "<group>"; };
329E746422CD02EA006F9797 /* BubbleReactionActionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BubbleReactionActionViewCell.xib; sourceTree = "<group>"; };
329E746522CD02EA006F9797 /* BubbleReactionActionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleReactionActionViewCell.swift; sourceTree = "<group>"; };
32A6000D22C661100042C1D9 /* EditHistoryViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewState.swift; sourceTree = "<group>"; };
32A6000E22C661100042C1D9 /* EditHistoryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewController.swift; sourceTree = "<group>"; };
32A6000F22C661100042C1D9 /* EditHistoryViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditHistoryViewModel.swift; sourceTree = "<group>"; };
@@ -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 */,
+2 -4
View File
@@ -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";
+6 -14
View File
@@ -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 {
@@ -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
}
}
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="BubbleReactionActionViewCell" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="66" height="22"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="66" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jjn-uq-kYN">
<rect key="frame" x="1" y="1" width="64" height="20"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Show all" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gyn-ux-gmi">
<rect key="frame" x="6" y="4" width="52" height="12"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="gyn-ux-gmi" secondAttribute="trailing" constant="6" id="HAk-8U-Qky"/>
<constraint firstItem="gyn-ux-gmi" firstAttribute="leading" secondItem="jjn-uq-kYN" secondAttribute="leading" constant="6" id="OZ2-Xd-9f3"/>
<constraint firstItem="gyn-ux-gmi" firstAttribute="top" secondItem="jjn-uq-kYN" secondAttribute="top" constant="4" id="et3-mn-8dh"/>
<constraint firstAttribute="bottom" secondItem="gyn-ux-gmi" secondAttribute="bottom" constant="4" id="thv-mo-0kv"/>
</constraints>
</view>
</subviews>
</view>
<constraints>
<constraint firstItem="jjn-uq-kYN" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="1" id="E5H-9a-us9"/>
<constraint firstAttribute="bottom" secondItem="jjn-uq-kYN" secondAttribute="bottom" constant="1" id="Ggm-1f-3EB"/>
<constraint firstItem="jjn-uq-kYN" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="1" id="iT6-rk-qd6"/>
<constraint firstAttribute="trailing" secondItem="jjn-uq-kYN" secondAttribute="trailing" constant="1" id="ztM-7J-Dnf"/>
</constraints>
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
<size key="customSize" width="443" height="170"/>
<connections>
<outlet property="actionLabel" destination="gyn-ux-gmi" id="qme-DX-UAc"/>
</connections>
<point key="canvasLocation" x="-459.4202898550725" y="-207.58928571428569"/>
</collectionViewCell>
</objects>
</document>
@@ -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)
}
}
}
@@ -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..<Constants.maxItemsWhenLimited])
showAllButtonState = .showAll
}
}
let reactionsViewData = reactions.map { (reactionCount) -> BubbleReactionViewData in
return BubbleReactionViewData(emoji: reactionCount.reaction, countString: "\(reactionCount.count)", isCurrentUserReacted: reactionCount.myUserHasReacted)
}
self.viewDelegate?.bubbleReactionsViewModel(self, didUpdateViewState: .loaded(reactionsViewData: reactionsViewData, showAllButtonState: showAllButtonState))
}
}
@@ -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 {
@@ -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
@@ -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<NSString* /* eventId */> *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
+28 -1
View File
@@ -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<MXKRoomBubbleCellDataStoring> 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