session-ios/Signal/src/ViewControllers/FingerprintViewController.m

343 lines
13 KiB
Mathematica
Raw Normal View History

2014-10-29 21:58:58 +01:00
//
2017-02-17 23:30:49 +01:00
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
2014-10-29 21:58:58 +01:00
//
#import "FingerprintViewController.h"
#import "Environment.h"
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
#import "OWSConversationSettingsTableViewController.h"
#import "Signal-Swift.h"
#import "UIUtil.h"
#import "UIViewController+CameraPermissions.h"
#import <SignalServiceKit/NSDate+millisecondTimeStamp.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/OWSFingerprint.h>
#import <SignalServiceKit/OWSFingerprintBuilder.h>
#import <SignalServiceKit/OWSIdentityManager.h>
#import <SignalServiceKit/TSInfoMessage.h>
#import <SignalServiceKit/TSStorageManager+SessionStore.h>
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
2014-10-29 21:58:58 +01:00
NS_ASSUME_NONNULL_BEGIN
2014-12-11 00:05:41 +01:00
@interface FingerprintViewController () <OWSHighlightableLabelDelegate, OWSCompareSafetyNumbersActivityDelegate>
@property (nonatomic) TSStorageManager *storageManager;
@property (nonatomic) OWSFingerprint *fingerprint;
@property (nonatomic) NSString *contactName;
@property (nonatomic) OWSQRCodeScanningViewController *qrScanningController;
@property (nonatomic) IBOutlet UINavigationBar *modalNavigationBar;
@property (nonatomic) IBOutlet UIBarButtonItem *dismissModalButton;
@property (nonatomic) IBOutlet UIBarButtonItem *shareButton;
@property (nonatomic) IBOutlet UIView *qrScanningView;
@property (nonatomic) IBOutlet UILabel *scanningInstructions;
@property (nonatomic) IBOutlet UIView *scanningContainer;
@property (nonatomic) IBOutlet UIView *instructionsContainer;
@property (nonatomic) IBOutlet UIView *qrContainer;
@property (nonatomic) IBOutlet UIView *privacyVerificationQRCodeFrame;
@property (nonatomic) IBOutlet UIImageView *privacyVerificationQRCode;
@property (nonatomic) IBOutlet OWSHighlightableLabel *privacyVerificationFingerprint;
@property (nonatomic) IBOutlet UILabel *instructionsLabel;
@property (nonatomic) IBOutlet UIButton *scanButton;
2014-10-29 21:58:58 +01:00
@end
2014-10-29 21:58:58 +01:00
@implementation FingerprintViewController
- (void)configureWithRecipientId:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
self.storageManager = [TSStorageManager sharedManager];
OWSContactsManager *contactsManager = [Environment getCurrent].contactsManager;
self.contactName = [contactsManager displayNameForPhoneIdentifier:recipientId];
OWSRecipientIdentity *_Nullable recipientIdentity =
[[OWSIdentityManager sharedManager] recipientIdentityForRecipientId:recipientId];
OWSAssert(recipientIdentity);
OWSFingerprintBuilder *builder =
[[OWSFingerprintBuilder alloc] initWithStorageManager:self.storageManager contactsManager:contactsManager];
self.fingerprint =
[builder fingerprintWithTheirSignalId:recipientId theirIdentityKey:recipientIdentity.identityKey];
2014-12-04 00:23:36 +01:00
}
- (void)viewDidLoad
{
2014-10-29 21:58:58 +01:00
[super viewDidLoad];
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
self.navigationItem.leftBarButtonItem = self.dismissModalButton;
self.navigationItem.rightBarButtonItem = self.shareButton;
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
[self.modalNavigationBar pushNavigationItem:self.navigationItem animated:NO];
// HACK for transparent navigation bar.
[self.modalNavigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.modalNavigationBar.shadowImage = [UIImage new];
self.modalNavigationBar.translucent = YES;
// HACK to get full width preview layer
CGRect oldFrame = self.qrScanningView.frame;
CGRect newFrame = CGRectMake(oldFrame.origin.x,
oldFrame.origin.y,
self.view.frame.size.width,
self.view.frame.size.height / 2.0f - oldFrame.origin.y);
self.qrScanningView.frame = newFrame;
// END HACK to get full width preview layer
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
self.title = NSLocalizedString(@"PRIVACY_VERIFICATION_TITLE", @"Navbar title");
NSString *instructionsFormat = NSLocalizedString(@"PRIVACY_VERIFICATION_INSTRUCTIONS",
@"Paragraph(s) shown alongside the safety number when verifying privacy with {{contact name}}");
self.instructionsLabel.text = [NSString stringWithFormat:instructionsFormat, self.contactName];
NSString *scanTitle = NSLocalizedString(@"SCAN_CODE_ACTION",
@"Button label presented with camera icon while verifying privacy credentials. Shows the camera interface.");
[self.scanButton setTitle:scanTitle forState:UIControlStateNormal];
self.scanningInstructions.text
= NSLocalizedString(@"SCAN_CODE_INSTRUCTIONS", @"label presented once scanning (camera) view is visible.");
// Safety numbers and QR Code
self.privacyVerificationFingerprint.text = self.fingerprint.displayableText;
self.privacyVerificationQRCode.image = self.fingerprint.image;
// Don't antialias QRCode
self.privacyVerificationQRCode.layer.magnificationFilter = kCAFilterNearest;
self.privacyVerificationFingerprint.delegate = self;
2014-10-29 21:58:58 +01:00
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// On iOS8, the QRCodeFrame hasn't been layed out yet (causing the QRCode to be hidden), force it here.
[self.privacyVerificationQRCodeFrame setNeedsLayout];
[self.privacyVerificationQRCodeFrame layoutIfNeeded];
// Round QR Code.
self.privacyVerificationQRCodeFrame.layer.masksToBounds = YES;
self.privacyVerificationQRCodeFrame.layer.cornerRadius = self.privacyVerificationQRCodeFrame.frame.size.height / 2;
}
- (void)viewWillAppear:(BOOL)animated
{
// In case we're returning from activity view that needed default system styles.
[UIUtil applySignalAppearence];
}
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:YES];
if (self.dismissDelegate) {
[self.dismissDelegate presentedModalWasDismissed];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
{
if ([segue.identifier isEqualToString:@"embedIdentityQRScanner"]) {
OWSQRCodeScanningViewController *qrScanningController
= (OWSQRCodeScanningViewController *)segue.destinationViewController;
self.qrScanningController = qrScanningController;
qrScanningController.scanDelegate = self;
}
}
#pragma mark - HilightableLableDelegate
- (void)didHighlightLabel:(OWSHighlightableLabel *)label completion:(nullable void (^)(void))completionHandler
{
[self showSharingActivityWithCompletion:completionHandler];
}
- (void)showSharingActivityWithCompletion:(nullable void (^)(void))completionHandler
{
DDLogDebug(@"%@ Sharing safety numbers", self.tag);
OWSCompareSafetyNumbersActivity *compareActivity = [[OWSCompareSafetyNumbersActivity alloc] initWithDelegate:self];
NSString *shareFormat = NSLocalizedString(@"SAFETY_NUMBER_SHARE_FORMAT", @"Snippet to share {{safety number}} with a friend. sent e.g. via SMS");
NSString *shareString = [NSString stringWithFormat:shareFormat, self.fingerprint.displayableText];
UIActivityViewController *activityController =
[[UIActivityViewController alloc] initWithActivityItems:@[ shareString ]
applicationActivities:@[ compareActivity ]];
activityController.completionWithItemsHandler = ^void(UIActivityType __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError){
if (completionHandler) {
completionHandler();
}
[UIUtil applySignalAppearence];
};
// This value was extracted by inspecting `activityType` in the activityController.completionHandler
NSString *const iCloudActivityType = @"com.apple.CloudDocsUI.AddToiCloudDrive";
activityController.excludedActivityTypes = @[
UIActivityTypePostToFacebook,
UIActivityTypePostToWeibo,
UIActivityTypeAirDrop,
UIActivityTypePostToTwitter,
iCloudActivityType // This isn't being excluded. RADAR https://openradar.appspot.com/27493621
];
[UIUtil applyDefaultSystemAppearence];
[self presentViewController:activityController animated:YES completion:nil];
}
#pragma mark - OWSCompareSafetyNumbersActivityDelegate
- (void)compareSafetyNumbersActivitySucceededWithActivity:(OWSCompareSafetyNumbersActivity *)activity
{
[self showVerificationSucceeded];
}
- (void)compareSafetyNumbersActivity:(OWSCompareSafetyNumbersActivity *)activity failedWithError:(NSError *)error
{
[self showVerificationFailedWithError:error];
}
2014-10-29 21:58:58 +01:00
#pragma mark - Action
- (IBAction)closeButtonAction:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
2014-10-29 21:58:58 +01:00
}
- (IBAction)didTapShareButton
{
[self showSharingActivityWithCompletion:nil];
}
- (IBAction)didTouchUpInsideScanButton:(id)sender
{
[self showScanner];
}
2014-12-12 17:15:00 +01:00
- (void)showScanner
{
2016-11-04 23:41:37 +01:00
[self ows_askForCameraPermissions:^{
// Camera stops capturing when "sharing" while in capture mode.
// Also, it's less obvious whats being "shared" at this point,
// so just disable sharing when in capture mode.
self.shareButton.enabled = NO;
2016-11-04 23:41:37 +01:00
DDLogInfo(@"%@ Showing Scanner", self.tag);
self.qrScanningView.hidden = NO;
self.scanningInstructions.hidden = NO;
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.scanningContainer.frame = self.qrContainer.frame;
self.qrContainer.frame = self.instructionsContainer.frame;
self.instructionsContainer.alpha = 0.0f;
}
completion:nil];
[self.qrScanningController startCapture];
}
alertActionHandler:nil];
}
#pragma mark - OWSQRScannerDelegate
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithData:(NSData *)data
{
[self verifyCombinedFingerprintData:data];
}
- (void)verifyCombinedFingerprintData:(NSData *)combinedFingerprintData
{
NSError *error;
if ([self.fingerprint matchesLogicalFingerprintsData:combinedFingerprintData error:&error]) {
[self showVerificationSucceeded];
} else {
[self showVerificationFailedWithError:error];
}
}
- (void)showVerificationSucceeded
{
DDLogInfo(@"%@ Successfully verified privacy.", self.tag);
NSString *successTitle = NSLocalizedString(@"SUCCESSFUL_VERIFICATION_TITLE", nil);
NSString *dismissText = NSLocalizedString(@"DISMISS_BUTTON_TEXT", nil);
NSString *descriptionFormat = NSLocalizedString(
@"SUCCESSFUL_VERIFICATION_DESCRIPTION", @"Alert body after verifying privacy with {{other user's name}}");
NSString *successDescription = [NSString stringWithFormat:descriptionFormat, self.contactName];
UIAlertController *successAlertController =
[UIAlertController alertControllerWithTitle:successTitle
message:successDescription
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *dismissAction =
[UIAlertAction actionWithTitle:dismissText style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[self dismissViewControllerAnimated:true completion:nil];
}];
[successAlertController addAction:dismissAction];
[self presentViewController:successAlertController animated:YES completion:nil];
}
- (void)showVerificationFailedWithError:(NSError *)error
{
NSString *_Nullable failureTitle;
if (error.code != OWSErrorCodeUserError) {
failureTitle = NSLocalizedString(@"FAILED_VERIFICATION_TITLE", @"alert title");
} // else no title. We don't want to show a big scary "VERIFICATION FAILED" when it's just user error.
UIAlertController *failureAlertController =
[UIAlertController alertControllerWithTitle:failureTitle
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
NSString *dismissText = NSLocalizedString(@"DISMISS_BUTTON_TEXT", nil);
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:dismissText style:UIAlertActionStyleCancel handler: ^(UIAlertAction *action){
// Restore previous layout
self.shareButton.enabled = YES;
self.qrScanningView.hidden = YES;
self.scanningInstructions.hidden = YES;
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.instructionsContainer.alpha = 1.0f;
self.qrContainer.frame = self.scanningContainer.frame;
}
completion:nil];
}];
[failureAlertController addAction:dismissAction];
// TODO
// NSString retryText = NSLocalizedString(@"RETRY_BUTTON_TEXT", nil);
// UIAlertAction *retryAction = [UIAlertAction actionWithTitle:retryText style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * _Nonnull action) {
//
// }];
// [failureAlertController addAction:retryAction];
[self presentViewController:failureAlertController animated:YES completion:nil];
DDLogWarn(@"%@ Identity verification failed with error: %@", self.tag, error);
}
2014-10-29 21:58:58 +01:00
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(nullable void (^)(void))completion
{
self.qrScanningView.hidden = YES;
[super dismissViewControllerAnimated:flag completion:completion];
}
Disappearing Messages * Per thread settings menu accessed by tapping on thread title This removed the toggle-phone behavior. You'll be able to see the phone number in the settings table view. This removed the "add contact" functionality, although it was already broken for ios>=9 (which is basically everybody). The group actions menu was absorbed into this screen * Added a confirm alert to leave group (fixes #938) * New Translation Strings * Extend "Add People" label to fit translations. * resolved issues with translations not fitting in group menu * Fix the long standing type warning where TSCalls were assigned to a TSMessageAdapter. * Can delete info messages Follow the JSQMVC pattern and put UIResponder-able content in the messageBubbleContainer. This gives us more functionality *and* allows us to delete some code. yay! It's still not yet possible to delete phone messages. =( * Fixed some compiler warnings. * xcode8 touching storyboard. So long xcode7! * Fixup multiline info messages. We were seeing info messages like "You set disappearing message timer to 10" instead of "You set disappearing message timer to 10 seconds." Admittedly this isn't a very good fix, as now one liners feel like they have too much padding. If the message is well over one line, we were wrapping properly, but there's a problem when the message is *just barely* two lines, the cell height grows, but the label still thinks it's just one line (as evinced by the one line appearing in the center of the label frame. The result being that the last word of the label is cropped. * Disable group actions after leaving group. // FREEBIE
2016-09-21 14:37:51 +02:00
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
2014-10-29 21:58:58 +01:00
}
@end
NS_ASSUME_NONNULL_END