mirror of https://github.com/oxen-io/session-ios
Merge branch 'mkirk/dismiss-share-view'
commit
71f56ef3da
@ -1,212 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "SendExternalFileViewController.h"
|
|
||||||
#import "Environment.h"
|
|
||||||
#import "NSString+OWS.h"
|
|
||||||
#import "SignalApp.h"
|
|
||||||
#import "ThreadUtil.h"
|
|
||||||
#import "UIColor+OWS.h"
|
|
||||||
#import "UIFont+OWS.h"
|
|
||||||
#import "UIView+OWS.h"
|
|
||||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
|
||||||
#import <SignalServiceKit/OWSMessageSender.h>
|
|
||||||
#import <SignalServiceKit/TSThread.h>
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
@interface SendExternalFileViewController () <SelectThreadViewControllerDelegate,
|
|
||||||
AttachmentApprovalViewControllerDelegate>
|
|
||||||
|
|
||||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
|
||||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
|
||||||
@property (nonatomic) TSThread *thread;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
#pragma mark -
|
|
||||||
|
|
||||||
@implementation SendExternalFileViewController
|
|
||||||
|
|
||||||
- (instancetype)init
|
|
||||||
{
|
|
||||||
if (self = [super init]) {
|
|
||||||
self.delegate = self;
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)loadView
|
|
||||||
{
|
|
||||||
[super loadView];
|
|
||||||
|
|
||||||
_contactsManager = [Environment current].contactsManager;
|
|
||||||
_messageSender = [Environment current].messageSender;
|
|
||||||
|
|
||||||
self.title = NSLocalizedString(@"SEND_EXTERNAL_FILE_VIEW_TITLE", @"Title for the 'send external file' view.");
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)canSelectBlockedContact
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable UIView *)createHeaderWithSearchBar:(UISearchBar *)searchBar
|
|
||||||
{
|
|
||||||
OWSAssert(searchBar)
|
|
||||||
|
|
||||||
const CGFloat imageSize
|
|
||||||
= ScaleFromIPhone5To7Plus(40, 50);
|
|
||||||
const CGFloat imageLabelSpacing = ScaleFromIPhone5To7Plus(5, 8);
|
|
||||||
const CGFloat titleVSpacing = ScaleFromIPhone5To7Plus(10, 15);
|
|
||||||
const CGFloat contentVMargin = 20;
|
|
||||||
|
|
||||||
UIView *header = [UIView new];
|
|
||||||
header.backgroundColor = [UIColor whiteColor];
|
|
||||||
|
|
||||||
UIView *titleLabel = [self createTitleLabel];
|
|
||||||
[titleLabel sizeToFit];
|
|
||||||
[header addSubview:titleLabel];
|
|
||||||
[titleLabel autoHCenterInSuperview];
|
|
||||||
[titleLabel autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:contentVMargin];
|
|
||||||
|
|
||||||
UIView *fileView = [UIView new];
|
|
||||||
[header addSubview:fileView];
|
|
||||||
[fileView autoHCenterInSuperview];
|
|
||||||
[fileView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:titleLabel withOffset:titleVSpacing];
|
|
||||||
|
|
||||||
UIImage *image = [UIImage imageNamed:@"file-thin-black-filled-large"];
|
|
||||||
OWSAssert(image);
|
|
||||||
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
|
|
||||||
imageView.layer.minificationFilter = kCAFilterTrilinear;
|
|
||||||
imageView.layer.magnificationFilter = kCAFilterTrilinear;
|
|
||||||
imageView.layer.shadowColor = [UIColor blackColor].CGColor;
|
|
||||||
imageView.layer.shadowRadius = 2.f;
|
|
||||||
imageView.layer.shadowOpacity = 0.2f;
|
|
||||||
imageView.layer.shadowOffset = CGSizeMake(0.75f, 0.75f);
|
|
||||||
[fileView addSubview:imageView];
|
|
||||||
[imageView autoSetDimension:ALDimensionWidth toSize:imageSize];
|
|
||||||
[imageView autoSetDimension:ALDimensionHeight toSize:imageSize];
|
|
||||||
[imageView autoPinLeadingToSuperview];
|
|
||||||
[imageView autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
|
||||||
[imageView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
|
||||||
|
|
||||||
UIView *fileNameLabel = [self createFileNameLabel];
|
|
||||||
[fileView addSubview:fileNameLabel];
|
|
||||||
[fileNameLabel autoAlignAxis:ALAxisHorizontal toSameAxisOfView:imageView];
|
|
||||||
[fileNameLabel autoPinLeadingToTrailingOfView:imageView margin:imageLabelSpacing];
|
|
||||||
[fileNameLabel autoPinTrailingToSuperview];
|
|
||||||
|
|
||||||
[header addSubview:searchBar];
|
|
||||||
[searchBar autoPinWidthToSuperview];
|
|
||||||
[searchBar autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:fileView withOffset:contentVMargin];
|
|
||||||
[searchBar autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
|
||||||
|
|
||||||
// UITableViewController.tableHeaderView must have its height set.
|
|
||||||
header.frame = CGRectMake(0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
(contentVMargin * 2 + titleLabel.frame.size.height + titleVSpacing + imageSize + searchBar.frame.size.height));
|
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)formattedFileName
|
|
||||||
{
|
|
||||||
// AppDelegate already verifies that this attachment has a valid filename.
|
|
||||||
//
|
|
||||||
// TODO: If we reuse this VC, for example to offer a "forward attachment to other thread",
|
|
||||||
// feature, this assumption would no longer apply.
|
|
||||||
OWSAssert(self.attachment);
|
|
||||||
NSString *filename = [self.attachment.sourceFilename ows_stripped];
|
|
||||||
OWSAssert(filename.length > 0);
|
|
||||||
const NSUInteger kMaxFilenameLength = 20;
|
|
||||||
if (filename.length > kMaxFilenameLength) {
|
|
||||||
// Truncate the filename if necessary.
|
|
||||||
//
|
|
||||||
// TODO: Use l10n-safe truncation.
|
|
||||||
filename = [[[filename substringToIndex:kMaxFilenameLength / 2] stringByAppendingString:@"…"]
|
|
||||||
stringByAppendingString:[filename substringFromIndex:filename.length - kMaxFilenameLength / 2]];
|
|
||||||
}
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIView *)createFileNameLabel
|
|
||||||
{
|
|
||||||
UILabel *label = [UILabel new];
|
|
||||||
label.text = [self formattedFileName];
|
|
||||||
label.textColor = [UIColor ows_materialBlueColor];
|
|
||||||
label.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(16.f, 20.f)];
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (UIView *)createTitleLabel
|
|
||||||
{
|
|
||||||
UILabel *label = [UILabel new];
|
|
||||||
label.text
|
|
||||||
= NSLocalizedString(@"SEND_EXTERNAL_FILE_HEADER_TITLE", @"Header title for the 'send external file' view.");
|
|
||||||
label.textColor = [UIColor blackColor];
|
|
||||||
label.font = [UIFont ows_mediumFontWithSize:ScaleFromIPhone5To7Plus(18.f, 20.f)];
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - SelectThreadViewControllerDelegate
|
|
||||||
|
|
||||||
- (void)threadWasSelected:(TSThread *)thread
|
|
||||||
{
|
|
||||||
OWSAssert(self.attachment);
|
|
||||||
OWSAssert(thread);
|
|
||||||
self.thread = thread;
|
|
||||||
|
|
||||||
__weak typeof(self) weakSelf = self;
|
|
||||||
|
|
||||||
// FIXME SHARINGEXTENSION
|
|
||||||
// Handling safety number changes brings in a lot of machinery.
|
|
||||||
// How do we want to handle this?
|
|
||||||
// e.g. fingerprint scanning, etc. in the SAE or just redirect the user to the main app?
|
|
||||||
// BOOL didShowSNAlert =
|
|
||||||
// [SafetyNumberConfirmationAlert presentAlertIfNecessaryWithRecipientIds:thread.recipientIdentifiers
|
|
||||||
// confirmationText:[SafetyNumberStrings
|
|
||||||
// confirmSendButton]
|
|
||||||
// contactsManager:self.contactsManager
|
|
||||||
// completion:^(BOOL didConfirm) {
|
|
||||||
// if (didConfirm) {
|
|
||||||
// [weakSelf threadWasSelected:thread];
|
|
||||||
// }
|
|
||||||
// }];
|
|
||||||
// if (didShowSNAlert) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
AttachmentApprovalViewController *approvalVC =
|
|
||||||
[[AttachmentApprovalViewController alloc] initWithAttachment:self.attachment delegate:self];
|
|
||||||
|
|
||||||
[self.navigationController pushViewController:approvalVC animated:YES];
|
|
||||||
|
|
||||||
// FIXME This implemenation was for the "import with signal" functionality,
|
|
||||||
// and is now broken. We need to be sure to remove the "import with signal" functionality.
|
|
||||||
// [SignalApp.sharedApp presentConversationForThread:thread];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - AttachmentApprovalViewControllerDelegate
|
|
||||||
|
|
||||||
- (void)didApproveAttachment
|
|
||||||
{
|
|
||||||
[ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
|
|
||||||
[ThreadUtil sendMessageWithAttachment:self.attachment inThread:self.thread messageSender:self.messageSender];
|
|
||||||
|
|
||||||
// FIXME SHARINGEXTENSION
|
|
||||||
// Show loading screen and dismiss entire share extension once entirely complete
|
|
||||||
[self.navigationController popViewControllerAnimated:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)didCancelAttachment
|
|
||||||
{
|
|
||||||
[self.navigationController popViewControllerAnimated:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
// All Observer methods will be invoked from the main thread.
|
||||||
|
@objc
|
||||||
|
public protocol ShareViewDelegate: class {
|
||||||
|
func shareViewWasCompleted()
|
||||||
|
func shareViewWasCancelled()
|
||||||
|
func shareViewFailed(error: Error)
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SharingThreadPickerViewController.h"
|
||||||
|
#import "Environment.h"
|
||||||
|
#import "NSString+OWS.h"
|
||||||
|
#import "SignalApp.h"
|
||||||
|
#import "ThreadUtil.h"
|
||||||
|
#import "UIColor+OWS.h"
|
||||||
|
#import "UIFont+OWS.h"
|
||||||
|
#import "UIView+OWS.h"
|
||||||
|
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||||
|
#import <SignalServiceKit/OWSMessageSender.h>
|
||||||
|
#import <SignalServiceKit/TSThread.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface SharingThreadPickerViewController () <SelectThreadViewControllerDelegate,
|
||||||
|
AttachmentApprovalViewControllerDelegate>
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||||
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||||
|
@property (nonatomic) TSThread *thread;
|
||||||
|
@property (nonatomic, readonly, weak) id<ShareViewDelegate> shareViewDelegate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
@implementation SharingThreadPickerViewController
|
||||||
|
|
||||||
|
- (instancetype)initWithShareViewDelegate:(id<ShareViewDelegate>)shareViewDelegate;
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
_shareViewDelegate = shareViewDelegate;
|
||||||
|
self.selectThreadViewDelegate = self;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadView
|
||||||
|
{
|
||||||
|
[super loadView];
|
||||||
|
|
||||||
|
_contactsManager = [Environment current].contactsManager;
|
||||||
|
_messageSender = [Environment current].messageSender;
|
||||||
|
|
||||||
|
self.title = NSLocalizedString(@"SEND_EXTERNAL_FILE_VIEW_TITLE", @"Title for the 'send external file' view.");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)canSelectBlockedContact
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable UIView *)createHeaderWithSearchBar:(UISearchBar *)searchBar
|
||||||
|
{
|
||||||
|
OWSAssert(searchBar)
|
||||||
|
|
||||||
|
const CGFloat contentVMargin
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
UIView *header = [UIView new];
|
||||||
|
header.backgroundColor = [UIColor whiteColor];
|
||||||
|
|
||||||
|
UIButton *cancelShareButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||||
|
[header addSubview:cancelShareButton];
|
||||||
|
|
||||||
|
[cancelShareButton setTitle:[CommonStrings cancelButton] forState:UIControlStateNormal];
|
||||||
|
cancelShareButton.userInteractionEnabled = YES;
|
||||||
|
|
||||||
|
[cancelShareButton autoPinEdgeToSuperviewMargin:ALEdgeLeading];
|
||||||
|
[cancelShareButton autoPinEdgeToSuperviewMargin:ALEdgeBottom];
|
||||||
|
[cancelShareButton setCompressionResistanceHigh];
|
||||||
|
[cancelShareButton setContentHuggingHigh];
|
||||||
|
|
||||||
|
[cancelShareButton addTarget:self
|
||||||
|
action:@selector(didTapCancelShareButton)
|
||||||
|
forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
|
||||||
|
[header addSubview:searchBar];
|
||||||
|
[searchBar autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:cancelShareButton withOffset:6];
|
||||||
|
[searchBar autoPinEdgeToSuperviewEdge:ALEdgeTrailing];
|
||||||
|
[searchBar autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
||||||
|
[searchBar autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
||||||
|
|
||||||
|
UIView *borderView = [UIView new];
|
||||||
|
[header addSubview:borderView];
|
||||||
|
|
||||||
|
borderView.backgroundColor = [UIColor colorWithRGBHex:0xbbbbbb];
|
||||||
|
[borderView autoSetDimension:ALDimensionHeight toSize:0.5];
|
||||||
|
[borderView autoPinWidthToSuperview];
|
||||||
|
[borderView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
||||||
|
|
||||||
|
// UITableViewController.tableHeaderView must have its height set.
|
||||||
|
header.frame = CGRectMake(0, 0, 0, (contentVMargin * 2 + searchBar.frame.size.height));
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - SelectThreadViewControllerDelegate
|
||||||
|
|
||||||
|
- (void)threadWasSelected:(TSThread *)thread
|
||||||
|
{
|
||||||
|
OWSAssert(self.attachment);
|
||||||
|
OWSAssert(thread);
|
||||||
|
self.thread = thread;
|
||||||
|
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
// FIXME SHARINGEXTENSION
|
||||||
|
// Handling safety number changes brings in a lot of machinery.
|
||||||
|
// How do we want to handle this?
|
||||||
|
// e.g. fingerprint scanning, etc. in the SAE or just redirect the user to the main app?
|
||||||
|
// BOOL didShowSNAlert =
|
||||||
|
// [SafetyNumberConfirmationAlert presentAlertIfNecessaryWithRecipientIds:thread.recipientIdentifiers
|
||||||
|
// confirmationText:[SafetyNumberStrings
|
||||||
|
// confirmSendButton]
|
||||||
|
// contactsManager:self.contactsManager
|
||||||
|
// completion:^(BOOL didConfirm) {
|
||||||
|
// if (didConfirm) {
|
||||||
|
// [weakSelf threadWasSelected:thread];
|
||||||
|
// }
|
||||||
|
// }];
|
||||||
|
// if (didShowSNAlert) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
AttachmentApprovalViewController *approvalVC =
|
||||||
|
[[AttachmentApprovalViewController alloc] initWithAttachment:self.attachment delegate:self];
|
||||||
|
|
||||||
|
[self.navigationController pushViewController:approvalVC animated:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didTapCancelShareButton
|
||||||
|
{
|
||||||
|
DDLogDebug(@"%@ tapped cancel share button", self.logTag);
|
||||||
|
[self cancelShareExperience];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cancelShareExperience
|
||||||
|
{
|
||||||
|
[self.shareViewDelegate shareViewWasCancelled];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - AttachmentApprovalViewControllerDelegate
|
||||||
|
|
||||||
|
- (void)didApproveAttachment
|
||||||
|
{
|
||||||
|
[ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
|
||||||
|
[ThreadUtil sendMessageWithAttachment:self.attachment inThread:self.thread messageSender:self.messageSender];
|
||||||
|
|
||||||
|
// This is just a temporary hack while testing to hopefully not dismiss too early.
|
||||||
|
// FIXME Show progress dialog
|
||||||
|
// FIXME don't dismiss until sending is complete
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
[self.shareViewDelegate shareViewWasCompleted];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didCancelAttachment
|
||||||
|
{
|
||||||
|
[self cancelShareExperience];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
Loading…
Reference in New Issue