element-ios/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCe...

230 lines
9.7 KiB
Objective-C

/*
Copyright 2018-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
#import "RoomSelectedStickerBubbleCell.h"
#import "RoomEncryptedDataBubbleCell.h"
#import "RoomIncomingAttachmentBubbleCell.h"
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
#import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h"
#import "RoomIncomingEncryptedAttachmentBubbleCell.h"
#import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
#import "ThemeService.h"
#import "GeneratedInterface-Swift.h"
@implementation RoomSelectedStickerBubbleCell
- (void)awakeFromNib
{
[super awakeFromNib];
// define arrow mask
CAShapeLayer *arrowMaskLayer = [[CAShapeLayer alloc] init];
arrowMaskLayer.frame = self.arrowView.bounds;
CGSize viewSize = self.arrowView.frame.size;
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(0, viewSize.height)]; // arrow left bottom point
[path addLineToPoint:CGPointMake(viewSize.width / 2, 0)]; // arrow head
[path addLineToPoint:CGPointMake(viewSize.width, viewSize.height)]; // arrow right bottom point
[path closePath]; // arrow top side
arrowMaskLayer.path = path.CGPath;
self.arrowView.layer.mask = arrowMaskLayer;
self.arrowView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
self.descriptionView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
[self.descriptionView.layer setCornerRadius:10];
}
- (void)render:(MXKCellData *)cellData
{
[self prepareRender:cellData];
if (bubbleData)
{
// Retrieve the component which stores the sticker (Only one component is handled by the bubble in case of sticker).
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents.firstObject;
// Handle the pagination and the sender information
// Look for the original cell class to extract the constraints value.
Class<MXKCellRendering> modelCellViewClass = nil;
if (bubbleData.shouldHideSenderInformation)
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class;
self.paginationTitleView.hidden = YES;
self.pictureView.hidden = YES;
self.userNameLabel.hidden = YES;
self.userNameTapGestureMaskView.userInteractionEnabled = NO;
}
else
{
if (bubbleData.isPaginationFirstBubble)
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class;
self.paginationTitleView.hidden = NO;
self.paginationLabel.text = [[bubbleData.eventFormatter dateStringFromDate:bubbleData.date withTime:NO] uppercaseString];
}
else
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentBubbleCell.class : RoomIncomingAttachmentBubbleCell.class;
self.paginationTitleView.hidden = YES;
}
// Hanlde sender avatar (Supposed his avatar is stored unencrypted on Matrix media repo)
self.pictureView.hidden = NO;
self.pictureView.enableInMemoryCache = YES;
[self.pictureView setImageURI:bubbleData.senderAvatarUrl
withType:nil
andImageOrientation:UIImageOrientationUp
toFitViewSize:self.pictureView.frame.size
withMethod:MXThumbnailingMethodCrop
previewImage:bubbleData.senderAvatarPlaceholder ? bubbleData.senderAvatarPlaceholder : self.picturePlaceholder
mediaManager:bubbleData.mxSession.mediaManager];
// Display sender's name except if the name appears in the displayed text (see emote and membership events)
if (bubbleData.shouldHideSenderName == NO)
{
self.userNameLabel.text = bubbleData.senderDisplayName;
self.userNameLabel.hidden = NO;
self.userNameTapGestureMaskView.userInteractionEnabled = YES;
}
else
{
self.userNameLabel.hidden = YES;
self.userNameTapGestureMaskView.userInteractionEnabled = NO;
}
}
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
[timelineConfiguration.currentStyle.cellLayoutUpdater updateLayoutForSelectedStickerCell:self];
// Retrieve the suitable content size for the attachment thumbnail
CGSize contentSize = bubbleData.contentSize;
// Update image view frame in order to center loading wheel (if any)
CGRect frame = self.attachmentView.frame;
frame.size.width = contentSize.width;
frame.size.height = contentSize.height;
self.attachmentView.frame = frame;
// Retrieve the MIME type
NSString *mimetype = nil;
if (bubbleData.attachment.thumbnailInfo)
{
mimetype = bubbleData.attachment.thumbnailInfo[@"mimetype"];
}
else if (bubbleData.attachment.contentInfo)
{
mimetype = bubbleData.attachment.contentInfo[@"mimetype"];
}
// Display the sticker
self.attachmentView.backgroundColor = [UIColor clearColor];
[self.attachmentView setAttachmentThumb:bubbleData.attachment];
// Set the description
NSAttributedString *description = component.attributedTextMessage;
if (description.length)
{
self.descriptionContainerView.hidden = NO;
self.descriptionLabel.attributedText = description;
}
else
{
self.descriptionContainerView.hidden = YES;
}
// Adjust Attachment width constant
self.attachViewWidthConstraint.constant = contentSize.width;
// Handle the encryption view
if (bubbleData.isEncryptedRoom)
{
// Set the right device info icon
self.encryptionStatusView.hidden = NO;
self.encryptionStatusView.image = [RoomEncryptedDataBubbleCell encryptionIconForBubbleComponent:component];
}
else
{
self.encryptionStatusView.hidden = YES;
}
// Hide by default the info container
self.bubbleInfoContainer.hidden = YES;
// Adjust the layout according to the original cell, the one used to display the sticker unselected.
if ([modelCellViewClass nib])
{
MXKRoomBubbleTableViewCell* cell= (MXKRoomBubbleTableViewCell*)[[modelCellViewClass nib] instantiateWithOwner:nil options:nil].firstObject;
if (cell.userNameLabel)
{
frame = cell.userNameLabel.frame;
self.userNameLabelTopConstraint.constant = frame.origin.y;
}
frame = cell.attachmentView.frame;
self.attachViewLeadingConstraint.constant = frame.origin.x;
self.attachViewTopConstraint.constant = cell.attachViewTopConstraint.constant;
self.attachViewBottomConstraint.constant = cell.attachViewBottomConstraint.constant;
self.bubbleInfoContainerTopConstraint.constant = cell.bubbleInfoContainerTopConstraint.constant;
}
}
}
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
// Sanity check: accept only object of MXKRoomBubbleCellData classes or sub-classes
NSParameterAssert([cellData isKindOfClass:[MXKRoomBubbleCellData class]]);
MXKRoomBubbleCellData *bubbleData = (MXKRoomBubbleCellData*)cellData;
// Look for the original cell class to extract the constraints value.
Class modelCellViewClass = nil;
if (bubbleData.shouldHideSenderInformation)
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class;
}
else
{
if (bubbleData.isPaginationFirstBubble)
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class;
}
else
{
modelCellViewClass = bubbleData.isEncryptedRoom ? RoomIncomingEncryptedAttachmentBubbleCell.class : RoomIncomingAttachmentBubbleCell.class;
}
}
CGFloat rowHeight = [modelCellViewClass heightForCellData:cellData withMaximumWidth:maxWidth];
// Finalize the cell height by adding the height of the description.
// Retrieve the component which stores the sticker (Only one component is handled by the bubble in case of sticker).
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents.firstObject;
NSAttributedString *description = component.attributedTextMessage;
if (description.length)
{
RoomSelectedStickerBubbleCell* cell = (RoomSelectedStickerBubbleCell*)[self cellWithOriginalXib];
CGRect frame = cell.frame;
frame.size.width = maxWidth;
frame.size.height = 300;
cell.frame = frame;
cell.descriptionLabel.attributedText = description;
[cell layoutIfNeeded];
rowHeight += cell.descriptionContainerView.frame.size.height + cell.descriptionContainerViewBottomConstraint.constant;
}
return rowHeight;
}
@end