session-ios/Session/Conversations/Views & Cells/OWSGenericAttachmentView.m

243 lines
7.9 KiB
Mathematica
Raw Normal View History

2017-10-10 22:13:54 +02:00
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
2017-10-10 22:13:54 +02:00
//
#import "OWSGenericAttachmentView.h"
#import "OWSBezierPathView.h"
2019-05-02 23:58:48 +02:00
#import "Session-Swift.h"
2017-10-10 22:13:54 +02:00
#import "UIFont+OWS.h"
#import "UIView+OWS.h"
2020-11-16 00:34:47 +01:00
2020-11-11 07:45:50 +01:00
#import <SignalUtilitiesKit/OWSFormat.h>
#import <SignalUtilitiesKit/UIColor+OWS.h>
2020-11-20 04:04:56 +01:00
#import <SessionUtilitiesKit/MIMETypeUtil.h>
2020-11-26 00:37:56 +01:00
#import <SessionUtilitiesKit/NSString+SSK.h>
2020-11-23 00:24:40 +01:00
#import <SessionMessagingKit/TSAttachmentStream.h>
2020-11-12 00:41:45 +01:00
#import <SignalCoreKit/NSString+OWS.h>
2017-10-10 22:13:54 +02:00
NS_ASSUME_NONNULL_BEGIN
@interface OWSGenericAttachmentView ()
@property (nonatomic) TSAttachment *attachment;
@property (nonatomic, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, weak) id<ConversationViewItem> viewItem;
2017-10-10 22:13:54 +02:00
@property (nonatomic) BOOL isIncoming;
2018-06-29 15:54:22 +02:00
@property (nonatomic) UILabel *topLabel;
@property (nonatomic) UILabel *bottomLabel;
2017-10-10 22:13:54 +02:00
@end
#pragma mark -
@implementation OWSGenericAttachmentView
- (instancetype)initWithAttachment:(TSAttachment *)attachment
isIncoming:(BOOL)isIncoming
viewItem:(id<ConversationViewItem>)viewItem
2017-10-10 22:13:54 +02:00
{
self = [super init];
if (self) {
_attachment = attachment;
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
_attachmentStream = (TSAttachmentStream *)attachment;
}
2017-10-10 22:13:54 +02:00
_isIncoming = isIncoming;
_viewItem = viewItem;
2017-10-10 22:13:54 +02:00
}
return self;
}
2018-05-01 22:16:44 +02:00
#pragma mark -
2017-10-10 22:13:54 +02:00
2018-06-27 20:53:31 +02:00
- (CGFloat)hMargin
2017-10-10 22:13:54 +02:00
{
2018-06-27 20:53:31 +02:00
return 0.f;
2017-10-10 22:13:54 +02:00
}
2018-06-27 21:13:15 +02:00
- (CGFloat)hSpacing
2017-10-10 22:13:54 +02:00
{
2018-05-04 19:06:26 +02:00
return 8.f;
2017-10-10 22:13:54 +02:00
}
2018-06-29 15:54:22 +02:00
- (CGFloat)vMargin
2017-10-10 22:13:54 +02:00
{
2020-09-04 06:50:06 +02:00
return 4.f;
2017-10-10 22:13:54 +02:00
}
2018-06-29 15:54:22 +02:00
- (CGSize)measureSizeWithMaxMessageWidth:(CGFloat)maxMessageWidth
2017-10-10 22:13:54 +02:00
{
2018-06-29 15:54:22 +02:00
CGSize result = CGSizeZero;
2017-10-10 22:13:54 +02:00
2018-06-27 21:13:15 +02:00
CGFloat labelsHeight = ([OWSGenericAttachmentView topLabelFont].lineHeight +
[OWSGenericAttachmentView bottomLabelFont].lineHeight + [OWSGenericAttachmentView labelVSpacing]);
2018-06-29 15:54:22 +02:00
CGFloat contentHeight = MAX(self.iconHeight, labelsHeight);
result.height = contentHeight + self.vMargin * 2;
2017-10-10 22:13:54 +02:00
2018-06-29 15:54:22 +02:00
CGFloat labelsWidth
= MAX([self.topLabel sizeThatFits:CGSizeZero].width, [self.bottomLabel sizeThatFits:CGSizeZero].width);
CGFloat contentWidth = (self.iconWidth + labelsWidth + self.hSpacing);
result.width = MIN(maxMessageWidth, contentWidth + self.hMargin * 2);
return CGSizeCeil(result);
2017-10-10 22:13:54 +02:00
}
2018-06-29 15:54:22 +02:00
- (CGFloat)iconWidth
2017-10-10 22:13:54 +02:00
{
2018-06-29 15:54:22 +02:00
return 36.f;
2017-10-10 22:13:54 +02:00
}
2018-06-27 20:53:31 +02:00
- (CGFloat)iconHeight
2017-10-10 22:13:54 +02:00
{
2020-11-16 00:34:47 +01:00
return 48.0f;
2017-10-10 22:13:54 +02:00
}
2018-07-09 15:58:02 +02:00
- (void)createContentsWithConversationStyle:(ConversationStyle *)conversationStyle
2017-10-10 22:13:54 +02:00
{
OWSAssertDebug(conversationStyle);
2018-07-09 15:58:02 +02:00
2018-06-27 20:53:31 +02:00
self.axis = UILayoutConstraintAxisHorizontal;
self.alignment = UIStackViewAlignmentCenter;
2018-06-27 21:13:15 +02:00
self.spacing = self.hSpacing;
2018-07-17 00:30:18 +02:00
self.layoutMarginsRelativeArrangement = YES;
2020-09-04 06:50:06 +02:00
self.layoutMargins = UIEdgeInsetsMake(self.vMargin, 0, self.vMargin - 4, 0);
2017-10-10 22:13:54 +02:00
2018-06-27 20:53:31 +02:00
// attachment_file
UIImage *image = [UIImage imageNamed:@"generic-attachment"];
OWSAssertDebug(image);
OWSAssertDebug(image.size.width == self.iconWidth);
OWSAssertDebug(image.size.height == self.iconHeight);
2017-10-10 22:13:54 +02:00
UIImageView *imageView = [UIImageView new];
2018-06-27 20:53:31 +02:00
imageView.image = image;
[self addArrangedSubview:imageView];
[imageView setContentHuggingHigh];
NSString *_Nullable filename = self.attachment.sourceFilename;
2018-06-29 16:25:36 +02:00
if (!filename) {
2018-09-04 16:25:42 +02:00
filename = [[self.attachmentStream originalFilePath] lastPathComponent];
2018-06-29 16:25:36 +02:00
}
NSString *fileExtension = filename.pathExtension;
if (fileExtension.length < 1) {
fileExtension = [MIMETypeUtil fileExtensionForMIMEType:self.attachment.contentType];
2018-06-29 16:25:36 +02:00
}
UILabel *fileTypeLabel = [UILabel new];
fileTypeLabel.text = fileExtension.localizedUppercaseString;
2018-09-19 16:08:27 +02:00
fileTypeLabel.textColor = [UIColor ows_gray90Color];
2018-06-29 16:25:36 +02:00
fileTypeLabel.lineBreakMode = NSLineBreakByTruncatingTail;
fileTypeLabel.font = [UIFont ows_dynamicTypeCaption1Font].ows_mediumWeight;
fileTypeLabel.adjustsFontSizeToFitWidth = YES;
fileTypeLabel.textAlignment = NSTextAlignmentCenter;
// Center on icon.
[imageView addSubview:fileTypeLabel];
[fileTypeLabel autoCenterInSuperview];
[fileTypeLabel autoSetDimension:ALDimensionWidth toSize:self.iconWidth - 20.f];
[self replaceIconWithDownloadProgressIfNecessary:imageView];
2018-06-27 20:53:31 +02:00
UIStackView *labelsView = [UIStackView new];
labelsView.axis = UILayoutConstraintAxisVertical;
2018-06-27 21:13:15 +02:00
labelsView.spacing = [OWSGenericAttachmentView labelVSpacing];
2018-06-27 20:53:31 +02:00
labelsView.alignment = UIStackViewAlignmentLeading;
[self addArrangedSubview:labelsView];
2017-10-10 22:13:54 +02:00
NSString *topText = [self.attachment.sourceFilename ows_stripped];
2017-10-10 22:13:54 +02:00
if (topText.length < 1) {
topText = [MIMETypeUtil fileExtensionForMIMEType:self.attachment.contentType].localizedUppercaseString;
2017-10-10 22:13:54 +02:00
}
if (topText.length < 1) {
topText = NSLocalizedString(@"GENERIC_ATTACHMENT_LABEL", @"A label for generic attachments.");
}
UILabel *topLabel = [UILabel new];
2018-06-29 15:54:22 +02:00
self.topLabel = topLabel;
2017-10-10 22:13:54 +02:00
topLabel.text = topText;
2018-07-09 15:58:02 +02:00
topLabel.textColor = [conversationStyle bubbleTextColorWithIsIncoming:self.isIncoming];
2017-10-10 22:13:54 +02:00
topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
2018-06-27 22:00:44 +02:00
topLabel.font = [OWSGenericAttachmentView topLabelFont];
2018-06-27 20:53:31 +02:00
[labelsView addArrangedSubview:topLabel];
2017-10-10 22:13:54 +02:00
unsigned long long fileSize = 0;
if (self.attachmentStream) {
NSError *error;
fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:[self.attachmentStream originalFilePath]
error:&error]
.fileSize;
OWSAssertDebug(!error);
}
2019-03-18 19:24:33 +01:00
// We don't want to show the file size while the attachment is downloading.
// To avoid layout jitter when the download completes, we reserve space in
// the layout using a whitespace string.
NSString *bottomText = @" ";
if (fileSize > 0) {
bottomText = [OWSFormat formatFileSize:fileSize];
}
2017-10-10 22:13:54 +02:00
UILabel *bottomLabel = [UILabel new];
2018-06-29 15:54:22 +02:00
self.bottomLabel = bottomLabel;
2017-10-10 22:13:54 +02:00
bottomLabel.text = bottomText;
2018-07-09 15:58:02 +02:00
bottomLabel.textColor = [conversationStyle bubbleSecondaryTextColorWithIsIncoming:self.isIncoming];
2017-10-10 22:13:54 +02:00
bottomLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
2018-06-27 21:13:15 +02:00
bottomLabel.font = [OWSGenericAttachmentView bottomLabelFont];
2018-06-27 20:53:31 +02:00
[labelsView addArrangedSubview:bottomLabel];
2017-10-10 22:13:54 +02:00
}
- (void)replaceIconWithDownloadProgressIfNecessary:(UIView *)iconView
{
if (!self.viewItem.attachmentPointer) {
return;
}
switch (self.viewItem.attachmentPointer.state) {
case TSAttachmentPointerStateFailed:
// We don't need to handle the "tap to retry" state here,
// only download progress.
return;
case TSAttachmentPointerStateEnqueued:
case TSAttachmentPointerStateDownloading:
break;
}
switch (self.viewItem.attachmentPointer.pointerType) {
case TSAttachmentPointerTypeRestoring:
// TODO: Show "restoring" indicator and possibly progress.
return;
case TSAttachmentPointerTypeUnknown:
case TSAttachmentPointerTypeIncoming:
break;
}
NSString *_Nullable uniqueId = self.viewItem.attachmentPointer.uniqueId;
if (uniqueId.length < 1) {
OWSFailDebug(@"Missing uniqueId.");
return;
}
CGSize iconViewSize = [iconView sizeThatFits:CGSizeZero];
CGFloat downloadViewSize = MIN(iconViewSize.width, iconViewSize.height);
MediaDownloadView *downloadView =
[[MediaDownloadView alloc] initWithAttachmentId:uniqueId radius:downloadViewSize * 0.5f];
iconView.layer.opacity = 0.01f;
[self addSubview:downloadView];
[downloadView autoSetDimensionsToSize:CGSizeMake(downloadViewSize, downloadViewSize)];
[downloadView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:iconView];
[downloadView autoAlignAxis:ALAxisVertical toSameAxisOfView:iconView];
}
2018-06-27 21:13:15 +02:00
+ (UIFont *)topLabelFont
{
2020-01-15 03:56:19 +01:00
return [UIFont systemFontOfSize:LKValues.mediumFontSize];
2018-06-27 21:13:15 +02:00
}
+ (UIFont *)bottomLabelFont
{
2018-07-12 21:02:25 +02:00
return [UIFont ows_dynamicTypeCaption1Font];
2018-06-27 21:13:15 +02:00
}
+ (CGFloat)labelVSpacing
{
return 2.f;
}
2017-10-10 22:13:54 +02:00
@end
NS_ASSUME_NONNULL_END