Merge pull request #1364 from vector-im/riot_1361

Bug Fix - Chat screen: the message overlaps its timestamp
This commit is contained in:
giomfo
2017-06-29 09:32:33 +02:00
committed by GitHub
14 changed files with 245 additions and 48 deletions
@@ -47,8 +47,15 @@ NSString *const kMXKRoomBubbleCellRiotEditButtonPressed = @"kMXKRoomBubbleCellRi
if (component && component.date)
{
// Check whether this is the first displayed component.
BOOL isFirstDisplayedComponent = (componentIndex == 0);
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
isFirstDisplayedComponent = (componentIndex == ((RoomBubbleCellData*)bubbleData).oldestComponentIndex);
}
CGFloat timeLabelPosX = self.bubbleInfoContainer.frame.size.width - VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH;
CGFloat timeLabelPosY = componentIndex ? component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant: 0;
CGFloat timeLabelPosY = isFirstDisplayedComponent ? 0 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant;
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeLabelPosX, timeLabelPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH , 18)];
timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date];
@@ -104,7 +111,7 @@ NSString *const kMXKRoomBubbleCellRiotEditButtonPressed = @"kMXKRoomBubbleCellRi
[NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]];
// Check whether a vertical whitespace was applied to display correctly the timestamp.
if (componentIndex || bubbleData.shouldHideSenderInformation || bubbleData.shouldHideSenderName)
if (!isFirstDisplayedComponent || bubbleData.shouldHideSenderInformation || bubbleData.shouldHideSenderName)
{
// Adjust the position of the potential encryption icon in this case.
if (self.encryptionStatusContainerView)
@@ -170,19 +177,30 @@ NSString *const kMXKRoomBubbleCellRiotEditButtonPressed = @"kMXKRoomBubbleCellRi
// Define the marker frame
CGFloat markPosY = component.position.y + self.msgTextViewTopConstraint.constant;
CGFloat markHeight;
if (componentIndex == bubbleComponents.count - 1)
NSInteger mostRecentComponentIndex = bubbleComponents.count - 1;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
// There is no component after this component in the cell,
// use the rest of the cell height
markHeight = self.contentView.frame.size.height - markPosY;
mostRecentComponentIndex = ((RoomBubbleCellData*)bubbleData).mostRecentComponentIndex;
}
else
// Compute the mark height.
// Use the rest of the cell height by default.
CGFloat markHeight = self.contentView.frame.size.height - markPosY;
if (componentIndex != mostRecentComponentIndex)
{
// Stop the marker height to the top of the next component in the cell
MXKRoomBubbleComponent *nextComponent = bubbleComponents[componentIndex + 1];
markHeight = nextComponent.position.y - component.position.y;
// There is another component (with display) after this component in the cell.
// Stop the marker height to the top of this component.
for (NSInteger index = componentIndex + 1; index < bubbleComponents.count; index ++)
{
MXKRoomBubbleComponent *nextComponent = bubbleComponents[index];
if (nextComponent.attributedTextMessage)
{
markHeight = nextComponent.position.y - component.position.y;
break;
}
}
}
UIView *markerView = [[UIView alloc] initWithFrame:CGRectMake(VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_X,
@@ -394,10 +412,17 @@ NSString *const kMXKRoomBubbleCellRiotEditButtonPressed = @"kMXKRoomBubbleCellRi
{
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[componentIndex];
// Check whether this is the first displayed component.
BOOL isFirstDisplayedComponent = (componentIndex == 0);
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
isFirstDisplayedComponent = (componentIndex == ((RoomBubbleCellData*)bubbleData).oldestComponentIndex);
}
// Define 'Edit' button frame
UIImage *editIcon = [UIImage imageNamed:@"edit_icon"];
CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH - 22 - editIcon.size.width / 2;
CGFloat editBtnPosY = componentIndex ? component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13 : -13;
CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13;
UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)];
[editButton setImage:editIcon forState:UIControlStateNormal];
+5
View File
@@ -37,6 +37,11 @@
*/
@property(nonatomic) NSString *selectedEventId;
/**
The index of the oldest component (component with a timestamp, and an actual display). NSNotFound by default.
*/
@property(nonatomic, readonly) NSInteger oldestComponentIndex;
/**
The index of the most recent component (component with a timestamp, and an actual display). NSNotFound by default.
*/
+21
View File
@@ -348,6 +348,27 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
}
}
- (NSInteger)oldestComponentIndex
{
// Update the related component index
NSInteger oldestComponentIndex = NSNotFound;
NSArray *components = self.bubbleComponents;
NSInteger index = 0;
while (index < components.count)
{
MXKRoomBubbleComponent *component = components[index];
if (component.attributedTextMessage && component.date)
{
oldestComponentIndex = index;
break;
}
index++;
}
return oldestComponentIndex;
}
- (NSInteger)mostRecentComponentIndex
{
// Update the related component index
@@ -95,6 +95,12 @@ NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon = @"kRoomEncrypt
for (NSUInteger componentIndex = 0; componentIndex < bubbleComponents.count; componentIndex++)
{
component = bubbleComponents[componentIndex];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
UIImage *icon = [RoomEncryptedDataBubbleCell encryptionIconForEvent:component.event andSession:bubbleData.mxSession];
UIImageView *encryptStatusImageView = [[UIImageView alloc] initWithImage:icon];
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomIncomingEncryptedTextMsgBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomOutgoingEncryptedTextMsgBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -88,4 +102,4 @@
}
}
@end
@end
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -88,4 +102,4 @@
}
}
@end
@end
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -88,4 +102,4 @@
}
}
@end
@end
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -88,4 +102,4 @@
}
}
@end
@end
@@ -18,6 +18,8 @@
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomBubbleCellData.h"
@implementation RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell
- (void)awakeFromNib
@@ -64,15 +66,27 @@
// Check which bubble component is displayed in front of the tapped line.
NSArray *bubbleComponents = bubbleData.bubbleComponents;
// Consider by default the first component
MXKRoomBubbleComponent *tappedComponent = bubbleComponents.firstObject;
// Consider by default the first display component
NSInteger firstComponentIndex = 0;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class])
{
firstComponentIndex = ((RoomBubbleCellData*)bubbleData).oldestComponentIndex;
}
MXKRoomBubbleComponent *tappedComponent = bubbleComponents[firstComponentIndex++];
CGPoint tapPoint = [sender locationInView:self.messageTextView];
for (NSInteger index = 1; index < bubbleComponents.count; index++)
for (NSInteger index = firstComponentIndex; index < bubbleComponents.count; index++)
{
// Here the bubble is composed by multiple text messages
MXKRoomBubbleComponent *component = bubbleComponents[index];
// Ignore components without display.
if (!component.attributedTextMessage)
{
continue;
}
if (tapPoint.y < component.position.y)
{
break;
@@ -88,4 +102,4 @@
}
}
@end
@end