Move URL preview properties from RoomBubbleCellData in MXKRoomBubbleComponent.

Stop breaking up the bubble data for links now that vertical whitespace is added.
This commit is contained in:
Doug 2021-09-27 18:15:48 +01:00
parent b35838e268
commit f44e1b098e
3 changed files with 72 additions and 107 deletions

View file

@ -15,7 +15,6 @@
*/
#import <MatrixKit/MatrixKit.h>
@class URLPreviewData;
extern NSString *const URLPreviewDidUpdateNotification;
@ -81,16 +80,6 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
*/
@property(nonatomic, readonly) CGFloat additionalContentHeight;
/**
The data necessary to show a URL preview.
*/
@property (nonatomic) URLPreviewData *urlPreviewData;
/**
Whether a URL preview should be displayed for this cell.
*/
@property (nonatomic) BOOL showURLPreview;
/**
MXKeyVerification object associated to key verification event when using key verification by direct message.
*/

View file

@ -180,11 +180,8 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
// Indicate that the text message layout should be recomputed.
[self invalidateTextLayout];
// Load a url preview if a link was detected
if (self.hasLink)
{
[self loadURLPreview];
}
// Load a url preview if necessary.
[self refreshURLPreviewForEventId:event.eventId];
}
return self;
@ -194,11 +191,8 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
{
NSUInteger retVal = [super updateEvent:eventId withEvent:event];
// Update any URL preview data too.
if (self.hasLink)
{
[self loadURLPreview];
}
// Update any URL preview data as necessary.
[self refreshURLPreviewForEventId:event.eventId];
return retVal;
}
@ -254,14 +248,6 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
return attributedTextMessage;
}
- (BOOL)hasLink
{
// Only check the last bubble component as -addEvent:andRoomState: will break up
// the data that way, to always show a URL preview at the bottom of the cell.
MXKRoomBubbleComponent *lastComponent = bubbleComponents.lastObject;
return (lastComponent && lastComponent.link);
}
- (BOOL)hasNoDisplay
{
if (self.tag == RoomBubbleCellDataTagKeyVerificationNoDisplay)
@ -598,24 +584,13 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
- (CGFloat)urlPreviewHeightForEventId:(NSString*)eventId
{
if (!RiotSettings.shared.roomScreenShowsURLPreviews || !self.showURLPreview)
MXKRoomBubbleComponent *component = [self bubbleComponentWithLinkForEventId:eventId];
if (!component.showURLPreview)
{
return 0;
}
NSInteger index = [self bubbleComponentIndexForEventId:eventId];
if (index >= bubbleComponents.count)
{
return 0;
}
MXKRoomBubbleComponent *component = self.bubbleComponents[index];
if (!component.link)
{
return 0;
}
return RoomBubbleCellLayout.urlPreviewViewTopMargin + [URLPreviewView contentViewHeightFor:self.urlPreviewData
return RoomBubbleCellLayout.urlPreviewViewTopMargin + [URLPreviewView contentViewHeightFor:component.urlPreviewData
fitting:self.maxTextViewWidth];
}
@ -748,6 +723,28 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
return selectedComponentIndex;
}
- (MXKRoomBubbleComponent *)bubbleComponentWithLinkForEventId:(NSString *)eventId
{
if (!RiotSettings.shared.roomScreenShowsURLPreviews)
{
return nil;
}
NSInteger index = [self bubbleComponentIndexForEventId:eventId];
if (index == NSNotFound)
{
return nil;
}
MXKRoomBubbleComponent *component = self.bubbleComponents[index];
if (!component.link)
{
return nil;
}
return component;
}
#pragma mark -
+ (NSAttributedString *)timestampVerticalWhitespace
@ -801,19 +798,6 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
{
BOOL shouldAddEvent = YES;
// For unencrypted rooms, don't allow any events to be added
// after a bubble component that contains a link so than any URL
// preview is for the last bubble component in the cell.
if (!self.isEncryptedRoom && self.hasLink && self.bubbleComponents.lastObject)
{
MXKRoomBubbleComponent *lastComponent = self.bubbleComponents.lastObject;
if (event.originServerTs > lastComponent.event.originServerTs)
{
shouldAddEvent = NO;
}
}
switch (self.tag)
{
case RoomBubbleCellDataTagKeyVerificationNoDisplay:
@ -857,27 +841,9 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
shouldAddEvent = NO;
break;
}
// If the message contains a link and comes before this cell data, don't add it to
// ensure that a URL preview is only shown for the last component on some new cell data.
if (!self.isEncryptedRoom && self.bubbleComponents.firstObject)
{
MXKRoomBubbleComponent *firstComponent = self.bubbleComponents.firstObject;
if (event.originServerTs < firstComponent.event.originServerTs)
{
NSString *messageBody = event.content[@"body"];
if (messageBody && [messageBody mxk_firstURLDetected])
{
shouldAddEvent = NO;
}
break;
}
}
}
break;
}
case MXEventTypeKeyVerificationStart:
case MXEventTypeKeyVerificationAccept:
case MXEventTypeKeyVerificationKey:
@ -928,14 +894,12 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
if (shouldAddEvent)
{
BOOL hadLink = self.hasLink;
shouldAddEvent = [super addEvent:event andRoomState:roomState];
// If the cell data now contains a link, set the preview data.
if (shouldAddEvent && self.hasLink && !hadLink)
// If the event was added, load any url preview data if necessary.
if (shouldAddEvent)
{
[self loadURLPreview];
[self refreshURLPreviewForEventId:event.eventId];
}
}
@ -1106,45 +1070,45 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
#pragma mark - URL Previews
- (void)loadURLPreview
- (void)refreshURLPreviewForEventId:(NSString *)eventId
{
// Get the last bubble component as that contains the link.
MXKRoomBubbleComponent *lastComponent = bubbleComponents.lastObject;
if (!lastComponent || !lastComponent.link)
// Get the event's component, but only if it has a link.
MXKRoomBubbleComponent *component = [self bubbleComponentWithLinkForEventId:eventId];
if (!component)
{
return;
}
// Don't show the preview if it has been dismissed already.
self.showURLPreview = ![URLPreviewService.shared hasClosedPreviewFrom:lastComponent.event];
if (!self.showURLPreview)
component.showURLPreview = ![URLPreviewService.shared hasClosedPreviewFrom:component.event];
if (!component.showURLPreview)
{
return;
}
// If there is existing preview data, the message has been edited
// Clear the data to show the loading state when the preview isn't cached
if (self.urlPreviewData)
// If there is existing preview data, the message has been edited.
// Clear the data to show the loading state when the preview isn't cached.
if (component.urlPreviewData)
{
self.urlPreviewData = nil;
component.urlPreviewData = nil;
}
// Set the preview data.
MXWeakify(self);
NSDictionary<NSString *, NSString*> *userInfo = @{
@"eventId": lastComponent.event.eventId,
@"eventId": eventId,
@"roomId": self.roomId
};
[URLPreviewService.shared previewFor:lastComponent.link
and:lastComponent.event
[URLPreviewService.shared previewFor:component.link
and:component.event
with:self.mxSession
success:^(URLPreviewData * _Nonnull urlPreviewData) {
MXStrongifyAndReturnIfNil(self);
// Update the preview data, indicate that the text message layout needs refreshing and send a notification for refresh
self.urlPreviewData = urlPreviewData;
component.urlPreviewData = urlPreviewData;
[self invalidateTextLayout];
[self setNeedsUpdateAdditionalContentHeight];
@ -1156,7 +1120,9 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
MXLogDebug(@"[RoomBubbleCellData] Failed to get url preview")
// Don't show a preview and send a notification for refresh
self.showURLPreview = NO;
component.showURLPreview = NO;
[self invalidateTextLayout];
[self setNeedsUpdateAdditionalContentHeight];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:URLPreviewDidUpdateNotification object:nil userInfo:userInfo];

View file

@ -343,7 +343,7 @@ const CGFloat kTypingCellHeight = 24;
// Handle read receipts and read marker display.
// Ignore the read receipts on the bubble without actual display.
// Ignore the read receipts on collapsed bubbles
if ((((self.showBubbleReceipts && cellData.readReceipts.count) || cellData.reactions.count || cellData.showURLPreview) && !isCollapsableCellCollapsed) || self.showReadMarker)
if ((((self.showBubbleReceipts && cellData.readReceipts.count) || cellData.reactions.count || cellData.hasLink) && !isCollapsableCellCollapsed) || self.showReadMarker)
{
// Read receipts container are inserted here on the right side into the content view.
// Some vertical whitespaces are added in message text view (see RoomBubbleCellData class) to insert correctly multiple receipts.
@ -369,14 +369,13 @@ const CGFloat kTypingCellHeight = 24;
continue;
}
NSURL *link = component.link;
URLPreviewView *urlPreviewView;
// Show a URL preview if the component has a link that should be previewed.
if (link && RiotSettings.shared.roomScreenShowsURLPreviews && cellData.showURLPreview)
if (RiotSettings.shared.roomScreenShowsURLPreviews && component.showURLPreview)
{
urlPreviewView = [URLPreviewView instantiate];
urlPreviewView.preview = cellData.urlPreviewData;
urlPreviewView.preview = component.urlPreviewData;
urlPreviewView.delegate = self;
[temporaryViews addObject:urlPreviewView];
@ -1220,37 +1219,48 @@ const CGFloat kTypingCellHeight = 24;
// Use the link stored in the bubble component when opening the URL as we only
// store the sanitized URL in the preview data which may differ to the message content.
RoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventID];
if (!cellData)
{
return;
}
MXKRoomBubbleComponent *lastComponent = cellData.bubbleComponents.lastObject;
if (!lastComponent)
NSInteger index = [cellData bubbleComponentIndexForEventId:eventID];
if (index == NSNotFound)
{
return;
}
[UIApplication.sharedApplication vc_open:lastComponent.link completionHandler:nil];
MXKRoomBubbleComponent *component = cellData.bubbleComponents[index];
[UIApplication.sharedApplication vc_open:component.link completionHandler:nil];
}
- (void)didCloseURLPreviewView:(URLPreviewView *)previewView for:(NSString *)eventID in:(NSString *)roomID
{
RoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventID];
if (!cellData)
{
return;
}
NSInteger index = [cellData bubbleComponentIndexForEventId:eventID];
if (index == NSNotFound)
{
return;
}
MXKRoomBubbleComponent *component = cellData.bubbleComponents[index];
// Remember that the user closed the preview so it isn't shown again.
[URLPreviewService.shared closePreviewFor:eventID in:roomID];
// Hide the preview, remove its data and refresh the cells.
cellData.showURLPreview = NO;
cellData.urlPreviewData = nil;
component.showURLPreview = NO;
component.urlPreviewData = nil;
[cellData invalidateTextLayout];
[cellData setNeedsUpdateAdditionalContentHeight];
[self refreshCells];
}