From 1a71e61a66ad74c02ee300c187babdc4f600a8a0 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 9 Mar 2021 11:59:54 +0100 Subject: [PATCH] Improve the status of send messages (sending, sent, received, failed) - update after review --- .../MXKRoomBubbleTableViewCell+Riot.h | 5 + .../MXKRoomBubbleTableViewCell+Riot.m | 84 +++++++++++ .../Room/CellData/RoomBubbleCellData.h | 5 + .../Room/CellData/RoomBubbleCellData.m | 1 + .../Modules/Room/DataSources/RoomDataSource.m | 136 ++---------------- 5 files changed, 103 insertions(+), 128 deletions(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h index a36edb2fc..054e23b7c 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h @@ -152,6 +152,11 @@ extern NSString *const kMXKRoomBubbleCellCallBackButtonPressed; - (IBAction)onProgressLongPressGesture:(UILongPressGestureRecognizer*)recognizer; +/** + update tick view(s) according to the current sent state. + */ +- (void)updateTickView; + /** Blur the view by adding a transparent overlay. Default is NO. */ diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index e8ebf4a9d..15341b82e 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -669,6 +669,81 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa return rowHeight; } +- (void)updateTickView +{ + for (UIView *tickView in self.messageStatusViews) + { + [tickView removeFromSuperview]; + } + self.messageStatusViews = nil; + + NSMutableArray *statusViews = [NSMutableArray new]; + UIView *tickView = nil; + if ([bubbleData isKindOfClass:RoomBubbleCellData.class] + && ((RoomBubbleCellData*)bubbleData).componentIndexOfSentMessageTick >= 0) + { + UIImage *image = [UIImage imageNamed:@"sent_message_tick"]; + image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + tickView = [[UIImageView alloc] initWithImage:image]; + tickView.tintColor = ThemeService.shared.theme.messageTickColor; + [statusViews addObject:tickView]; + [self addTickView:tickView atIndex:((RoomBubbleCellData*)bubbleData).componentIndexOfSentMessageTick]; + } + + NSInteger index = bubbleData.bubbleComponents.count; + while (index--) + { + MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[index]; + NSArray *receipts = bubbleData.readReceipts[component.event.eventId]; + if (receipts.count == 0) { + if (component.event.sentState == MXEventSentStateUploading + || component.event.sentState == MXEventSentStateEncrypting + || component.event.sentState == MXEventSentStatePreparing + || component.event.sentState == MXEventSentStateSending) + { + if (bubbleData.attachment && component.event.sentState != MXEventSentStateSending) + { + UIView *progressContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; + CircleProgressView *progressView = [[CircleProgressView alloc] initWithFrame:CGRectMake(24, 24, 16, 16)]; + progressView.lineColor = ThemeService.shared.theme.messageTickColor; + [progressContentView addSubview:progressView]; + self.progressChartView = progressView; + + tickView = progressContentView; + + [progressView startAnimating]; + + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onProgressLongPressGesture:)]; + [tickView addGestureRecognizer:longPress]; + } + else + { + UIImage *image = [UIImage imageNamed:@"sending_message_tick"]; + image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + tickView = [[UIImageView alloc] initWithImage:image]; + tickView.tintColor = ThemeService.shared.theme.messageTickColor; + } + + [statusViews addObject:tickView]; + [self addTickView:tickView atIndex:index]; + } + } + + if (component.event.sentState == MXEventSentStateFailed) + { + tickView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"error_message_tick"]]; + [statusViews addObject:tickView]; + [self addTickView:tickView atIndex:index]; + } + } + + + if (statusViews.count) + { + self.messageStatusViews = statusViews; + } +} + #pragma mark - User actions - (IBAction)onEditButtonPressed:(id)sender @@ -704,6 +779,15 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa #pragma mark - Internals +- (void)addTickView:(UIView *)tickView atIndex:(NSInteger)index +{ + CGRect componentFrame = [self componentFrameInContentViewForIndex: index]; + + tickView.frame = CGRectMake(self.contentView.bounds.size.width - tickView.frame.size.width - 2 * RoomBubbleCellLayout.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height); + + [self.contentView addSubview:tickView]; +} + - (void)addEditButtonForComponent:(NSUInteger)componentIndex completion:(void (^ __nullable)(BOOL finished))completion { MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[componentIndex]; diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.h b/Riot/Modules/Room/CellData/RoomBubbleCellData.h index e69076042..7637153f0 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.h +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.h @@ -87,6 +87,11 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag) */ @property(nonatomic) BOOL isKeyVerificationOperationPending; +/** + Index of the component which needs a sent tick displayed. -1 if none. + */ +@property(nonatomic) NSInteger componentIndexOfSentMessageTick; + /** Indicate to update additional content height. */ diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 50444b09a..2f00e796b 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -53,6 +53,7 @@ static NSAttributedString *timestampVerticalWhitespace = nil; if (self) { _eventsToShowAllReactions = [NSMutableSet set]; + _componentIndexOfSentMessageTick = -1; } return self; } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 2f8d6c678..53b7f56dd 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -28,37 +28,6 @@ #import "MXRoom+Riot.h" -@interface CellDataComponentIndexPair : NSObject -@property (nonatomic, readonly) MXKCellData *cellData; -@property (nonatomic, readonly) NSInteger componentIndex; - -+ (instancetype)pairWithCellData:(MXKCellData *)cellData componentIndex:(NSInteger)componentIndex; -- (instancetype)initWithCellData:(MXKCellData *)cellData componentIndex:(NSInteger)componentIndex; - -@end - -@implementation CellDataComponentIndexPair - -+ (instancetype)pairWithCellData:(MXKCellData *)cellData componentIndex:(NSInteger)componentIndex -{ - return [[CellDataComponentIndexPair alloc] initWithCellData:cellData componentIndex:componentIndex]; -} - -- (instancetype)initWithCellData:(MXKCellData *)cellData componentIndex:(NSInteger)componentIndex -{ - self = [super init]; - - if (self) - { - _cellData = cellData; - _componentIndex = componentIndex; - } - - return self; -} - -@end - @interface RoomDataSource() { // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. @@ -78,8 +47,6 @@ @property(nonatomic, readwrite) RoomEncryptionTrustLevel encryptionTrustLevel; -@property (nonatomic, strong) CellDataComponentIndexPair *sentCell; - @property (nonatomic) RoomBubbleCellData *roomCreationCellData; @property (nonatomic) BOOL showRoomCreationCell; @@ -272,6 +239,7 @@ for (RoomBubbleCellData *cellData in bubbles) { cellData.containsLastMessage = NO; + cellData.componentIndexOfSentMessageTick = -1; } // The cell containing the last message is the last one with an actual display. @@ -648,7 +616,11 @@ [self setupAccessibilityForCell:bubbleCell withCellData:cellData]; - [self updateTickViewForBubbleCell:bubbleCell withCellData:cellData]; + // We are interested only by outgoing messages + if ([cellData.senderId isEqualToString: self.mxSession.credentials.userId]) + { + [bubbleCell updateTickView]; + } } return cell; @@ -1027,8 +999,6 @@ - (void)updateStatusInfo { - self.sentCell = nil; - NSInteger bubbleIndex = bubbles.count; while (bubbleIndex--) { @@ -1045,105 +1015,15 @@ MXEventSentState eventState = component.event.sentState; - if (self.sentCell == nil && eventState == MXEventSentStateSent) + if (eventState == MXEventSentStateSent) { - self.sentCell = [CellDataComponentIndexPair pairWithCellData:cellData componentIndex:componentIndex]; + cellData.componentIndexOfSentMessageTick = componentIndex; return; } } } } -- (void)updateTickViewForBubbleCell:(MXKRoomBubbleTableViewCell *)cell withCellData:(RoomBubbleCellData *)cellData -{ - // We are interested only by outgoing messages - if (![cellData.senderId isEqualToString: self.mxSession.credentials.userId]) - { - return; - } - - for (UIView *tickView in cell.messageStatusViews) - { - [tickView removeFromSuperview]; - } - cell.messageStatusViews = nil; - - NSMutableArray *statusViews = [NSMutableArray new]; - UIView *tickView = nil; - - if (cellData == self.sentCell.cellData) - { - UIImage *image = [UIImage imageNamed:@"sent_message_tick"]; - image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - tickView = [[UIImageView alloc] initWithImage:image]; - tickView.tintColor = ThemeService.shared.theme.messageTickColor; - [statusViews addObject:tickView]; - [self addTickView:tickView toCell:cell atIndex:self.sentCell.componentIndex]; - } - - NSInteger index = cellData.bubbleComponents.count; - while (index--) - { - MXKRoomBubbleComponent *component = cellData.bubbleComponents[index]; - NSArray *receipts = cellData.readReceipts[component.event.eventId]; - if (receipts.count == 0) { - if (component.event.sentState == MXEventSentStateUploading - || component.event.sentState == MXEventSentStateEncrypting - || component.event.sentState == MXEventSentStatePreparing - || component.event.sentState == MXEventSentStateSending) - { - if (cellData.attachment && component.event.sentState != MXEventSentStateSending) - { - UIView *progressContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - CircleProgressView *progressView = [[CircleProgressView alloc] initWithFrame:CGRectMake(24, 24, 16, 16)]; - progressView.lineColor = ThemeService.shared.theme.messageTickColor; - [progressContentView addSubview:progressView]; - cell.progressChartView = progressView; - - tickView = progressContentView; - - [progressView startAnimating]; - - UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:@selector(onProgressLongPressGesture:)]; - [tickView addGestureRecognizer:longPress]; - } - else - { - UIImage *image = [UIImage imageNamed:@"sending_message_tick"]; - image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - tickView = [[UIImageView alloc] initWithImage:image]; - tickView.tintColor = ThemeService.shared.theme.messageTickColor; - } - - [statusViews addObject:tickView]; - [self addTickView:tickView toCell:cell atIndex:index]; - } - } - - if (component.event.sentState == MXEventSentStateFailed) - { - tickView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"error_message_tick"]]; - [statusViews addObject:tickView]; - [self addTickView:tickView toCell:cell atIndex:index]; - } - } - - - if (statusViews.count) - { - cell.messageStatusViews = statusViews; - } -} - -- (void)addTickView:(UIView *)tickView toCell:(MXKRoomBubbleTableViewCell *)cell atIndex:(NSInteger)index -{ - CGRect componentFrame = [cell componentFrameInContentViewForIndex: index]; - - tickView.frame = CGRectMake(cell.contentView.bounds.size.width - tickView.frame.size.width - 2 * RoomBubbleCellLayout.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height); - - [cell.contentView addSubview:tickView]; -} - #pragma mark - Room creation intro cell - (BOOL)canShowRoomCreationIntroCell