mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge branch 'charlesmchen/attachmentApprovalInInputToolbar'
This commit is contained in:
commit
fb360cd41f
5 changed files with 188 additions and 37 deletions
|
@ -4,6 +4,8 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class SignalAttachment;
|
||||
|
||||
@protocol ConversationInputToolbarDelegate <NSObject>
|
||||
|
||||
- (void)sendButtonPressed;
|
||||
|
@ -20,6 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (void)textViewDidChange;
|
||||
|
||||
#pragma mark - Attachment Approval
|
||||
|
||||
- (void)didApproveAttachment:(SignalAttachment *)attachment;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -51,6 +57,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (void)cancelVoiceMemoIfNecessary;
|
||||
|
||||
#pragma mark - Attachment Approval
|
||||
|
||||
- (void)showApprovalUIForAttachment:(SignalAttachment *)attachment;
|
||||
- (void)viewWillAppear:(BOOL)animated;
|
||||
- (void)viewWillDisappear:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#import "ConversationInputToolbar.h"
|
||||
#import "ConversationInputTextView.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import "UIColor+OWS.h"
|
||||
#import "UIFont+OWS.h"
|
||||
#import "UIView+OWS.h"
|
||||
|
@ -16,6 +17,7 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
|
||||
@interface ConversationInputToolbar () <UIGestureRecognizerDelegate, ConversationTextViewToolbarDelegate>
|
||||
|
||||
@property (nonatomic, readonly) UIView *contentView;
|
||||
@property (nonatomic, readonly) ConversationInputTextView *inputTextView;
|
||||
@property (nonatomic, readonly) UIButton *attachmentButton;
|
||||
@property (nonatomic, readonly) UIButton *sendButton;
|
||||
|
@ -37,6 +39,12 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
@property (nonatomic) BOOL isRecordingVoiceMemo;
|
||||
@property (nonatomic) CGPoint voiceMemoGestureStartLocation;
|
||||
|
||||
#pragma mark - Attachment Approval
|
||||
|
||||
@property (nonatomic) UIView *attachmentApprovalView;
|
||||
@property (nonatomic, nullable) MediaMessageView *attachmentView;
|
||||
@property (nonatomic, nullable) SignalAttachment *attachmentToApprove;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -69,9 +77,13 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
[self addSubview:backgroundView];
|
||||
[backgroundView autoPinEdgesToSuperviewEdges];
|
||||
|
||||
_contentView = [UIView containerView];
|
||||
[self addSubview:self.contentView];
|
||||
[self.contentView autoPinEdgesToSuperviewEdges];
|
||||
|
||||
_inputTextView = [ConversationInputTextView new];
|
||||
self.inputTextView.textViewToolbarDelegate = self;
|
||||
[self addSubview:self.inputTextView];
|
||||
[self.contentView addSubview:self.inputTextView];
|
||||
|
||||
// We want to be permissive about taps on the send and attachment buttons,
|
||||
// so we use wrapper views that capture nearby taps. This is a lot easier
|
||||
|
@ -81,11 +93,11 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
_leftButtonWrapper = [UIView containerView];
|
||||
[self.leftButtonWrapper
|
||||
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(leftButtonTapped:)]];
|
||||
[self addSubview:self.leftButtonWrapper];
|
||||
[self.contentView addSubview:self.leftButtonWrapper];
|
||||
_rightButtonWrapper = [UIView containerView];
|
||||
[self.rightButtonWrapper
|
||||
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(rightButtonTapped:)]];
|
||||
[self addSubview:self.rightButtonWrapper];
|
||||
[self.contentView addSubview:self.rightButtonWrapper];
|
||||
|
||||
_attachmentButton = [[UIButton alloc] init];
|
||||
self.attachmentButton.accessibilityLabel
|
||||
|
@ -118,6 +130,10 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
self.voiceMemoButton.imageView.tintColor = [UIColor ows_materialBlueColor];
|
||||
[self.rightButtonWrapper addSubview:self.voiceMemoButton];
|
||||
|
||||
_attachmentApprovalView = [UIView containerView];
|
||||
[self addSubview:self.attachmentApprovalView];
|
||||
[self.attachmentApprovalView autoPinToSuperviewEdges];
|
||||
|
||||
// We want to be permissive about the voice message gesture, so we hang
|
||||
// the long press GR on the button's wrapper, not the button itself.
|
||||
UILongPressGestureRecognizer *longPressGestureRecognizer =
|
||||
|
@ -192,6 +208,33 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
{
|
||||
[NSLayoutConstraint deactivateConstraints:self.contentContraints];
|
||||
|
||||
if (self.attachmentToApprove) {
|
||||
self.contentView.hidden = YES;
|
||||
self.attachmentApprovalView.hidden = NO;
|
||||
|
||||
self.contentContraints = @[
|
||||
[self.attachmentApprovalView autoSetDimension:ALDimensionHeight toSize:300.f],
|
||||
];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self layoutIfNeeded];
|
||||
|
||||
// Ensure the keyboard is dismissed.
|
||||
//
|
||||
// NOTE: We need to do this _last_ or the layout changes in the input toolbar
|
||||
// will be inadvertently animated.
|
||||
[self.inputTextView resignFirstResponder];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self.contentView.hidden = NO;
|
||||
self.attachmentApprovalView.hidden = YES;
|
||||
self.attachmentView = nil;
|
||||
for (UIView *subview in self.attachmentApprovalView.subviews) {
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
|
||||
const int textViewVInset = 5;
|
||||
const int contentHInset = 6;
|
||||
const int contentHSpacing = 6;
|
||||
|
@ -626,6 +669,99 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Attachment Approval
|
||||
|
||||
- (void)showApprovalUIForAttachment:(SignalAttachment *)attachment
|
||||
{
|
||||
OWSAssert(attachment);
|
||||
|
||||
self.attachmentToApprove = attachment;
|
||||
|
||||
MediaMessageView *attachmentView = [[MediaMessageView alloc] initWithAttachment:attachment];
|
||||
self.attachmentView = attachmentView;
|
||||
[self.attachmentApprovalView addSubview:attachmentView];
|
||||
[attachmentView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:10];
|
||||
[attachmentView autoPinWidthToSuperviewWithMargin:20];
|
||||
|
||||
UIView *buttonRow = [UIView containerView];
|
||||
[self.attachmentApprovalView addSubview:buttonRow];
|
||||
[buttonRow autoPinWidthToSuperviewWithMargin:20];
|
||||
[buttonRow autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:attachmentView withOffset:10];
|
||||
[buttonRow autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:10];
|
||||
|
||||
// We use this invisible subview to ensure that the buttons are centered
|
||||
// horizontally.
|
||||
UIView *buttonSpacer = [UIView new];
|
||||
[buttonRow addSubview:buttonSpacer];
|
||||
// Vertical positioning of this view doesn't matter.
|
||||
[buttonSpacer autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
||||
[buttonSpacer autoSetDimension:ALDimensionWidth toSize:ScaleFromIPhone5To7Plus(20, 30)];
|
||||
[buttonSpacer autoSetDimension:ALDimensionHeight toSize:0];
|
||||
[buttonSpacer autoHCenterInSuperview];
|
||||
|
||||
UIView *cancelButton = [self createAttachmentApprovalButton:[CommonStrings cancelButton]
|
||||
color:[UIColor ows_destructiveRedColor]
|
||||
selector:@selector(attachmentApprovalCancelPressed)];
|
||||
[buttonRow addSubview:cancelButton];
|
||||
[cancelButton autoPinHeightToSuperview];
|
||||
[cancelButton autoPinEdge:ALEdgeRight toEdge:ALEdgeLeft ofView:buttonSpacer];
|
||||
|
||||
UIView *sendButton =
|
||||
[self createAttachmentApprovalButton:NSLocalizedString(
|
||||
@"ATTACHMENT_APPROVAL_SEND_BUTTON", comment
|
||||
: @"Label for 'send' button in the 'attachment approval' dialog.")
|
||||
color:[UIColor colorWithRGBHex:0x2ecc71]
|
||||
selector:@selector(attachmentApprovalSendPressed)];
|
||||
[buttonRow addSubview:sendButton];
|
||||
[sendButton autoPinHeightToSuperview];
|
||||
[sendButton autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:buttonSpacer];
|
||||
|
||||
[self ensureContentConstraints];
|
||||
}
|
||||
|
||||
- (UIView *)createAttachmentApprovalButton:(NSString *)title color:(UIColor *)color selector:(SEL)selector
|
||||
{
|
||||
const CGFloat buttonWidth = ScaleFromIPhone5To7Plus(110, 140);
|
||||
const CGFloat buttonHeight = ScaleFromIPhone5To7Plus(35, 45);
|
||||
|
||||
return [OWSFlatButton buttonWithTitle:title
|
||||
titleColor:[UIColor whiteColor]
|
||||
backgroundColor:color
|
||||
width:buttonWidth
|
||||
height:buttonHeight
|
||||
target:self
|
||||
selector:selector];
|
||||
}
|
||||
|
||||
- (void)attachmentApprovalCancelPressed
|
||||
{
|
||||
self.attachmentToApprove = nil;
|
||||
|
||||
[self ensureContentConstraints];
|
||||
}
|
||||
|
||||
- (void)attachmentApprovalSendPressed
|
||||
{
|
||||
SignalAttachment *attachment = self.attachmentToApprove;
|
||||
self.attachmentToApprove = nil;
|
||||
|
||||
if (attachment) {
|
||||
[self.inputToolbarDelegate didApproveAttachment:attachment];
|
||||
}
|
||||
|
||||
[self ensureContentConstraints];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[self.attachmentView viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[self.attachmentView viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)logTag
|
||||
|
|
|
@ -555,6 +555,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
// or on another device.
|
||||
[self hideInputIfNeeded];
|
||||
|
||||
[self.inputToolbar viewWillAppear:animated];
|
||||
|
||||
self.isViewVisible = YES;
|
||||
|
||||
// We should have already requested contact access at this point, so this should be a no-op
|
||||
|
@ -986,6 +988,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
|
||||
self.isViewVisible = NO;
|
||||
|
||||
[self.inputToolbar viewWillDisappear:animated];
|
||||
|
||||
[self.audioAttachmentPlayer stop];
|
||||
self.audioAttachmentPlayer = nil;
|
||||
|
||||
|
@ -3448,18 +3452,18 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
} else if (skipApprovalDialog) {
|
||||
[self sendMessageAttachment:attachment];
|
||||
} else {
|
||||
UIViewController *viewController =
|
||||
[[AttachmentApprovalViewController alloc] initWithAttachment:attachment
|
||||
successCompletion:^{
|
||||
[weakSelf sendMessageAttachment:attachment];
|
||||
}];
|
||||
UINavigationController *navigationController =
|
||||
[[UINavigationController alloc] initWithRootViewController:viewController];
|
||||
[self.navigationController presentViewController:navigationController animated:YES completion:nil];
|
||||
[self.inputToolbar showApprovalUIForAttachment:attachment];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)didApproveAttachment:(SignalAttachment *)attachment
|
||||
{
|
||||
OWSAssert(attachment);
|
||||
|
||||
[self sendMessageAttachment:attachment];
|
||||
}
|
||||
|
||||
- (void)showErrorAlertForAttachment:(SignalAttachment *_Nullable)attachment
|
||||
{
|
||||
OWSAssert(attachment == nil || [attachment hasError]);
|
||||
|
|
|
@ -62,8 +62,6 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
// MARK: - Create Views
|
||||
|
||||
private func createViews() {
|
||||
self.backgroundColor = UIColor.white
|
||||
|
||||
if attachment.isAnimatedImage {
|
||||
createAnimatedPreview()
|
||||
} else if attachment.isImage {
|
||||
|
@ -89,15 +87,15 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
subview.autoHCenterInSuperview()
|
||||
|
||||
if lastView == nil {
|
||||
subview.autoPinEdge(toSuperviewEdge:.top)
|
||||
subview.autoPinEdge(toSuperviewEdge: .top)
|
||||
} else {
|
||||
subview.autoPinEdge(.top, to:.bottom, of:lastView!, withOffset:10)
|
||||
subview.autoPinEdge(.top, to: .bottom, of: lastView!, withOffset: 10)
|
||||
}
|
||||
|
||||
lastView = subview
|
||||
}
|
||||
|
||||
lastView?.autoPinEdge(toSuperviewEdge:.bottom)
|
||||
lastView?.autoPinEdge(toSuperviewEdge: .bottom)
|
||||
|
||||
return stackView
|
||||
}
|
||||
|
@ -117,10 +115,10 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
setAudioIconToPlay()
|
||||
audioPlayButton.imageView?.layer.minificationFilter = kCAFilterTrilinear
|
||||
audioPlayButton.imageView?.layer.magnificationFilter = kCAFilterTrilinear
|
||||
audioPlayButton.addTarget(self, action:#selector(audioPlayButtonPressed), for:.touchUpInside)
|
||||
audioPlayButton.addTarget(self, action: #selector(audioPlayButtonPressed), for: .touchUpInside)
|
||||
let buttonSize = createHeroViewSize()
|
||||
audioPlayButton.autoSetDimension(.width, toSize:buttonSize)
|
||||
audioPlayButton.autoSetDimension(.height, toSize:buttonSize)
|
||||
audioPlayButton.autoSetDimension(.width, toSize: buttonSize)
|
||||
audioPlayButton.autoSetDimension(.height, toSize: buttonSize)
|
||||
subviews.append(audioPlayButton)
|
||||
|
||||
let fileNameLabel = createFileNameLabel()
|
||||
|
@ -136,7 +134,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
updateAudioStatusLabel()
|
||||
subviews.append(audioStatusLabel)
|
||||
|
||||
let stackView = wrapViewsInVerticalStack(subviews:subviews)
|
||||
let stackView = wrapViewsInVerticalStack(subviews: subviews)
|
||||
self.addSubview(stackView)
|
||||
fileNameLabel?.autoPinWidthToSuperview(withMargin: 32)
|
||||
stackView.autoPinWidthToSuperview()
|
||||
|
@ -152,7 +150,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
createGenericPreview()
|
||||
return
|
||||
}
|
||||
guard let image = YYImage(contentsOfFile:dataUrl.path) else {
|
||||
guard let image = YYImage(contentsOfFile: dataUrl.path) else {
|
||||
createGenericPreview()
|
||||
return
|
||||
}
|
||||
|
@ -166,14 +164,14 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
private func createImagePreview() {
|
||||
var image = attachment.image
|
||||
if image == nil {
|
||||
image = UIImage(data:attachment.data)
|
||||
image = UIImage(data: attachment.data)
|
||||
}
|
||||
guard image != nil else {
|
||||
createGenericPreview()
|
||||
return
|
||||
}
|
||||
|
||||
let imageView = UIImageView(image:image)
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.layer.minificationFilter = kCAFilterTrilinear
|
||||
imageView.layer.magnificationFilter = kCAFilterTrilinear
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
|
@ -186,7 +184,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
createGenericPreview()
|
||||
return
|
||||
}
|
||||
guard let videoPlayer = MPMoviePlayerController(contentURL:dataUrl) else {
|
||||
guard let videoPlayer = MPMoviePlayerController(contentURL: dataUrl) else {
|
||||
createGenericPreview()
|
||||
return
|
||||
}
|
||||
|
@ -214,7 +212,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
let fileSizeLabel = createFileSizeLabel()
|
||||
subviews.append(fileSizeLabel)
|
||||
|
||||
let stackView = wrapViewsInVerticalStack(subviews:subviews)
|
||||
let stackView = wrapViewsInVerticalStack(subviews: subviews)
|
||||
self.addSubview(stackView)
|
||||
fileNameLabel?.autoPinWidthToSuperview(withMargin: 32)
|
||||
stackView.autoPinWidthToSuperview()
|
||||
|
@ -227,9 +225,9 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
|
||||
private func createHeroImageView(imageName: String) -> UIView {
|
||||
let imageSize = createHeroViewSize()
|
||||
let image = UIImage(named:imageName)
|
||||
let image = UIImage(named: imageName)
|
||||
assert(image != nil)
|
||||
let imageView = UIImageView(image:image)
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.layer.minificationFilter = kCAFilterTrilinear
|
||||
imageView.layer.magnificationFilter = kCAFilterTrilinear
|
||||
imageView.layer.shadowColor = UIColor.black.cgColor
|
||||
|
@ -237,14 +235,14 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
imageView.layer.shadowRadius = CGFloat(2.0 * shadowScaling)
|
||||
imageView.layer.shadowOpacity = 0.25
|
||||
imageView.layer.shadowOffset = CGSize(width: 0.75 * shadowScaling, height: 0.75 * shadowScaling)
|
||||
imageView.autoSetDimension(.width, toSize:imageSize)
|
||||
imageView.autoSetDimension(.height, toSize:imageSize)
|
||||
imageView.autoSetDimension(.width, toSize: imageSize)
|
||||
imageView.autoSetDimension(.height, toSize: imageSize)
|
||||
|
||||
return imageView
|
||||
}
|
||||
|
||||
private func labelFont() -> UIFont {
|
||||
return UIFont.ows_regularFont(withSize:ScaleFromIPhone5To7Plus(18, 24))
|
||||
return UIFont.ows_regularFont(withSize: ScaleFromIPhone5To7Plus(18, 24))
|
||||
}
|
||||
|
||||
private func formattedFileExtension() -> String? {
|
||||
|
@ -252,7 +250,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
return nil
|
||||
}
|
||||
|
||||
return String(format:NSLocalizedString("ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT",
|
||||
return String(format: NSLocalizedString("ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT",
|
||||
comment: "Format string for file extension label in call interstitial view"),
|
||||
fileExtension.uppercased())
|
||||
}
|
||||
|
@ -287,7 +285,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
private func createFileSizeLabel() -> UIView {
|
||||
let label = UILabel()
|
||||
let fileSize = attachment.dataLength
|
||||
label.text = String(format:NSLocalizedString("ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT",
|
||||
label.text = String(format: NSLocalizedString("ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT",
|
||||
comment: "Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}."),
|
||||
ViewControllerUtils.formatFileSize(UInt(fileSize)))
|
||||
|
||||
|
@ -346,7 +344,7 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
|
||||
let isAudioPlaying = playbackState == .playing
|
||||
if isAudioPlaying && audioProgressSeconds > 0 && audioDurationSeconds > 0 {
|
||||
audioStatusLabel.text = String(format:"%@ / %@",
|
||||
audioStatusLabel.text = String(format: "%@ / %@",
|
||||
ViewControllerUtils.formatDurationSeconds(Int(round(self.audioProgressSeconds))),
|
||||
ViewControllerUtils.formatDurationSeconds(Int(round(self.audioDurationSeconds))))
|
||||
} else {
|
||||
|
@ -355,16 +353,16 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
|
|||
}
|
||||
|
||||
private func setAudioIconToPlay() {
|
||||
let image = UIImage(named:"audio_play_black_large")?.withRenderingMode(.alwaysTemplate)
|
||||
let image = UIImage(named: "audio_play_black_large")?.withRenderingMode(.alwaysTemplate)
|
||||
assert(image != nil)
|
||||
audioPlayButton?.setImage(image, for:.normal)
|
||||
audioPlayButton?.setImage(image, for: .normal)
|
||||
audioPlayButton?.imageView?.tintColor = UIColor.ows_materialBlue()
|
||||
}
|
||||
|
||||
private func setAudioIconToPause() {
|
||||
let image = UIImage(named:"audio_pause_black_large")?.withRenderingMode(.alwaysTemplate)
|
||||
let image = UIImage(named: "audio_pause_black_large")?.withRenderingMode(.alwaysTemplate)
|
||||
assert(image != nil)
|
||||
audioPlayButton?.setImage(image, for:.normal)
|
||||
audioPlayButton?.setImage(image, for: .normal)
|
||||
audioPlayButton?.imageView?.tintColor = UIColor.ows_materialBlue()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -383,6 +383,7 @@ class MessageMetadataViewController: OWSViewController {
|
|||
if let dataUTI = MIMETypeUtil.utiType(forMIMEType: contentType) {
|
||||
let attachment = SignalAttachment(dataSource: dataSource, dataUTI: dataUTI)
|
||||
let mediaMessageView = MediaMessageView(attachment: attachment)
|
||||
mediaMessageView.backgroundColor = UIColor.white
|
||||
self.mediaMessageView = mediaMessageView
|
||||
rows.append(mediaMessageView)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue