Move "attachment approval" into input toolbar.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 7e41489d82
commit 0fe76aaab8

@ -4,6 +4,8 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class SignalAttachment;
@protocol ConversationInputToolbarDelegate <NSObject> @protocol ConversationInputToolbarDelegate <NSObject>
- (void)sendButtonPressed; - (void)sendButtonPressed;
@ -20,6 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)textViewDidChange; - (void)textViewDidChange;
#pragma mark - Attachment Approval
- (void)didApproveAttachment:(SignalAttachment *)attachment;
@end @end
#pragma mark - #pragma mark -
@ -51,6 +57,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)cancelVoiceMemoIfNecessary; - (void)cancelVoiceMemoIfNecessary;
#pragma mark - Attachment Approval
- (void)showApprovalUIForAttachment:(SignalAttachment *)attachment;
- (void)viewWillAppear:(BOOL)animated;
- (void)viewWillDisappear:(BOOL)animated;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -4,6 +4,7 @@
#import "ConversationInputToolbar.h" #import "ConversationInputToolbar.h"
#import "ConversationInputTextView.h" #import "ConversationInputTextView.h"
#import "Signal-Swift.h"
#import "UIColor+OWS.h" #import "UIColor+OWS.h"
#import "UIFont+OWS.h" #import "UIFont+OWS.h"
#import "UIView+OWS.h" #import "UIView+OWS.h"
@ -16,6 +17,7 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
@interface ConversationInputToolbar () <UIGestureRecognizerDelegate, ConversationTextViewToolbarDelegate> @interface ConversationInputToolbar () <UIGestureRecognizerDelegate, ConversationTextViewToolbarDelegate>
@property (nonatomic, readonly) UIView *contentView;
@property (nonatomic, readonly) ConversationInputTextView *inputTextView; @property (nonatomic, readonly) ConversationInputTextView *inputTextView;
@property (nonatomic, readonly) UIButton *attachmentButton; @property (nonatomic, readonly) UIButton *attachmentButton;
@property (nonatomic, readonly) UIButton *sendButton; @property (nonatomic, readonly) UIButton *sendButton;
@ -37,6 +39,12 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
@property (nonatomic) BOOL isRecordingVoiceMemo; @property (nonatomic) BOOL isRecordingVoiceMemo;
@property (nonatomic) CGPoint voiceMemoGestureStartLocation; @property (nonatomic) CGPoint voiceMemoGestureStartLocation;
#pragma mark - Attachment Approval
@property (nonatomic) UIView *attachmentApprovalView;
@property (nonatomic, nullable) MediaMessageView *attachmentView;
@property (nonatomic, nullable) SignalAttachment *attachmentToApprove;
@end @end
#pragma mark - #pragma mark -
@ -69,9 +77,13 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
[self addSubview:backgroundView]; [self addSubview:backgroundView];
[backgroundView autoPinEdgesToSuperviewEdges]; [backgroundView autoPinEdgesToSuperviewEdges];
_contentView = [UIView containerView];
[self addSubview:self.contentView];
[self.contentView autoPinEdgesToSuperviewEdges];
_inputTextView = [ConversationInputTextView new]; _inputTextView = [ConversationInputTextView new];
self.inputTextView.textViewToolbarDelegate = self; 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, // 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 // 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]; _leftButtonWrapper = [UIView containerView];
[self.leftButtonWrapper [self.leftButtonWrapper
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(leftButtonTapped:)]]; addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(leftButtonTapped:)]];
[self addSubview:self.leftButtonWrapper]; [self.contentView addSubview:self.leftButtonWrapper];
_rightButtonWrapper = [UIView containerView]; _rightButtonWrapper = [UIView containerView];
[self.rightButtonWrapper [self.rightButtonWrapper
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(rightButtonTapped:)]]; addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(rightButtonTapped:)]];
[self addSubview:self.rightButtonWrapper]; [self.contentView addSubview:self.rightButtonWrapper];
_attachmentButton = [[UIButton alloc] init]; _attachmentButton = [[UIButton alloc] init];
self.attachmentButton.accessibilityLabel self.attachmentButton.accessibilityLabel
@ -118,6 +130,10 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
self.voiceMemoButton.imageView.tintColor = [UIColor ows_materialBlueColor]; self.voiceMemoButton.imageView.tintColor = [UIColor ows_materialBlueColor];
[self.rightButtonWrapper addSubview:self.voiceMemoButton]; [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 // 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. // the long press GR on the button's wrapper, not the button itself.
UILongPressGestureRecognizer *longPressGestureRecognizer = UILongPressGestureRecognizer *longPressGestureRecognizer =
@ -192,6 +208,27 @@ static void *kConversationInputTextViewObservingContext = &kConversationInputTex
{ {
[NSLayoutConstraint deactivateConstraints:self.contentContraints]; [NSLayoutConstraint deactivateConstraints:self.contentContraints];
if (self.attachmentToApprove) {
self.contentView.hidden = YES;
self.attachmentApprovalView.hidden = NO;
// Ensure the keyboard is dismissed.
[self.inputTextView resignFirstResponder];
self.contentContraints = @[
[self.attachmentApprovalView autoSetDimension:ALDimensionHeight toSize:300.f],
];
[self layoutIfNeeded];
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 textViewVInset = 5;
const int contentHInset = 6; const int contentHInset = 6;
const int contentHSpacing = 6; const int contentHSpacing = 6;
@ -626,6 +663,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 #pragma mark - Logging
+ (NSString *)logTag + (NSString *)logTag

@ -555,6 +555,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
// or on another device. // or on another device.
[self hideInputIfNeeded]; [self hideInputIfNeeded];
[self.inputToolbar viewWillAppear:animated];
self.isViewVisible = YES; self.isViewVisible = YES;
// We should have already requested contact access at this point, so this should be a no-op // 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.isViewVisible = NO;
[self.inputToolbar viewWillDisappear:animated];
[self.audioAttachmentPlayer stop]; [self.audioAttachmentPlayer stop];
self.audioAttachmentPlayer = nil; self.audioAttachmentPlayer = nil;
@ -3448,18 +3452,18 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
} else if (skipApprovalDialog) { } else if (skipApprovalDialog) {
[self sendMessageAttachment:attachment]; [self sendMessageAttachment:attachment];
} else { } else {
UIViewController *viewController = [self.inputToolbar showApprovalUIForAttachment:attachment];
[[AttachmentApprovalViewController alloc] initWithAttachment:attachment
successCompletion:^{
[weakSelf sendMessageAttachment:attachment];
}];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:viewController];
[self.navigationController presentViewController:navigationController animated:YES completion:nil];
} }
}); });
} }
- (void)didApproveAttachment:(SignalAttachment *)attachment
{
OWSAssert(attachment);
[self sendMessageAttachment:attachment];
}
- (void)showErrorAlertForAttachment:(SignalAttachment *_Nullable)attachment - (void)showErrorAlertForAttachment:(SignalAttachment *_Nullable)attachment
{ {
OWSAssert(attachment == nil || [attachment hasError]); OWSAssert(attachment == nil || [attachment hasError]);

@ -62,8 +62,6 @@ class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
// MARK: - Create Views // MARK: - Create Views
private func createViews() { private func createViews() {
self.backgroundColor = UIColor.white
if attachment.isAnimatedImage { if attachment.isAnimatedImage {
createAnimatedPreview() createAnimatedPreview()
} else if attachment.isImage { } else if attachment.isImage {

@ -383,6 +383,7 @@ class MessageMetadataViewController: OWSViewController {
if let dataUTI = MIMETypeUtil.utiType(forMIMEType: contentType) { if let dataUTI = MIMETypeUtil.utiType(forMIMEType: contentType) {
let attachment = SignalAttachment(dataSource: dataSource, dataUTI: dataUTI) let attachment = SignalAttachment(dataSource: dataSource, dataUTI: dataUTI)
let mediaMessageView = MediaMessageView(attachment: attachment) let mediaMessageView = MediaMessageView(attachment: attachment)
mediaMessageView.backgroundColor = UIColor.white
self.mediaMessageView = mediaMessageView self.mediaMessageView = mediaMessageView
rows.append(mediaMessageView) rows.append(mediaMessageView)
} }

Loading…
Cancel
Save