Merge branch 'charlesmchen/profileForNewAndOldUsers'

This commit is contained in:
Matthew Chen 2017-08-21 15:12:18 -04:00
commit 636790c991
16 changed files with 346 additions and 61 deletions

View file

@ -74,6 +74,7 @@
34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */; };
34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */; };
34B3F8A21E8EA6040035BE1A /* ViewControllerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */; };
34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */; };
34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; };
34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */; };
34CE88E71F2FB9A10098030F /* ProfileViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CE88E61F2FB9A10098030F /* ProfileViewController.m */; };
@ -505,6 +506,8 @@
34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = "<group>"; };
34B3F8A01E8EA6040035BE1A /* ViewControllerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewControllerUtils.h; sourceTree = "<group>"; };
34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllerUtils.m; sourceTree = "<group>"; };
34C42D591F45F7A80072EC04 /* OWSNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSNavigationController.h; sourceTree = "<group>"; };
34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSNavigationController.m; sourceTree = "<group>"; };
34CCAF361F0C0599004084F4 /* AppUpdateNag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppUpdateNag.h; sourceTree = "<group>"; };
34CCAF371F0C0599004084F4 /* AppUpdateNag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppUpdateNag.m; sourceTree = "<group>"; };
34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAddToContactViewController.h; sourceTree = "<group>"; };
@ -1026,6 +1029,8 @@
34B3F85F1E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.h */,
34B3F8601E8DF1700035BE1A /* OWSLinkedDevicesTableViewController.m */,
34B3F8611E8DF1700035BE1A /* OWSMessagesToolbarContentView.xib */,
34C42D591F45F7A80072EC04 /* OWSNavigationController.h */,
34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */,
34B3F8621E8DF1700035BE1A /* OWSQRCodeScanningViewController.h */,
34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */,
34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */,
@ -2307,6 +2312,7 @@
341BB7491DB727EE001E2975 /* JSQMediaItem+OWS.m in Sources */,
34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */,
45F2B1941D9C9F48000D2C69 /* OWSOutgoingMessageCollectionViewCell.m in Sources */,
34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */,
BFB074C919A5611000F2947C /* ObservableValue.m in Sources */,
B68EF9BA1C0B1EBD009C3DCD /* FLAnimatedImage.m in Sources */,
B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */,

View file

@ -11,6 +11,7 @@
#import "NotificationsManager.h"
#import "OWSContactsManager.h"
#import "OWSContactsSyncing.h"
#import "OWSNavigationController.h"
#import "OWSProfileManager.h"
#import "OWSStaleNotificationObserver.h"
#import "Pastelog.h"
@ -802,8 +803,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
self.window.rootViewController = navigationController;
} else {
RegistrationViewController *viewController = [RegistrationViewController new];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:viewController];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:viewController];
navigationController.navigationBarHidden = YES;
self.window.rootViewController = navigationController;
}

View file

@ -316,8 +316,7 @@
- (void)showProfile
{
ProfileViewController *vc = [[ProfileViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[ProfileViewController presentForAppSettings:self.navigationController];
}
- (void)showAdvanced

View file

@ -3,10 +3,8 @@
//
#import "CodeVerificationViewController.h"
#import "AppDelegate.h"
#import "ProfileViewController.h"
#import "Signal-Swift.h"
#import "SignalsNavigationController.h"
#import "SignalsViewController.h"
#import "StringUtil.h"
#import "UIViewController+OWS.h"
#import <PromiseKit/AnyPromise.h>
@ -269,14 +267,7 @@ NS_ASSUME_NONNULL_BEGIN
DDLogInfo(@"%@ Successfully registered Signal account.", weakSelf.tag);
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf stopActivityIndicator];
SignalsViewController *homeView = [SignalsViewController new];
homeView.newlyRegisteredUser = YES;
SignalsNavigationController *navigationController =
[[SignalsNavigationController alloc] initWithRootViewController:homeView];
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.window.rootViewController = navigationController;
OWSAssert([navigationController.topViewController isKindOfClass:[SignalsViewController class]]);
[weakSelf vericationWasCompleted];
});
})
.catch(^(NSError *_Nonnull error) {
@ -290,6 +281,10 @@ NS_ASSUME_NONNULL_BEGIN
});
}
- (void)vericationWasCompleted
{
[ProfileViewController presentForRegistration:self.navigationController];
}
- (void)presentAlertWithVerificationError:(NSError *)error
{

View file

@ -158,7 +158,6 @@ typedef enum : NSUInteger {
OWSVoiceMemoGestureDelegate,
UIDocumentMenuDelegate,
UIDocumentPickerDelegate,
UIGestureRecognizerDelegate,
UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
UITextViewDelegate>
@ -549,10 +548,6 @@ typedef enum : NSUInteger {
// In case we're dismissing a CNContactViewController which requires default system appearance
[UIUtil applySignalAppearence];
// Since we're using a custom back button, we have to do some extra work to manage the
// interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.delegate = self;
// We need to recheck on every appearance, since the user may have left the group in the settings VC,
// or on another device.
[self hideInputIfNeeded];
@ -992,10 +987,6 @@ typedef enum : NSUInteger {
self.isViewVisible = NO;
// Since we're using a custom back button, we have to do some extra work to manage the
// interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
[self.audioAttachmentPlayer stop];
self.audioAttachmentPlayer = nil;

View file

@ -10,6 +10,7 @@
#import "ContactsViewHelper.h"
#import "Environment.h"
#import "OWSContactsManager.h"
#import "OWSNavigationController.h"
#import "OWSTableViewController.h"
#import "Signal-Swift.h"
#import "SignalKeyingStorage.h"
@ -34,7 +35,8 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
AvatarViewHelperDelegate,
AddToGroupViewControllerDelegate,
OWSTableViewControllerDelegate,
UINavigationControllerDelegate>
UINavigationControllerDelegate,
OWSNavigationView>
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@ -97,8 +99,6 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
[super loadView];
self.title = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @"The navbar title for the 'new group' view.");
self.navigationItem.leftBarButtonItem =
[self createOWSBackButtonWithTarget:self selector:@selector(backButtonPressed:)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(@"NEW_GROUP_CREATE_BUTTON", @"The title for the 'create group' button.")
@ -547,7 +547,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
#pragma mark - Event Handling
- (void)backButtonPressed:(id)sender
- (void)backButtonPressed
{
[self.groupNameTextField resignFirstResponder];
@ -649,6 +649,17 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
return [self.memberRecipientIds containsObject:recipientId];
}
#pragma mark - OWSNavigationView
- (BOOL)shouldCancelNavigationBack
{
BOOL result = self.hasUnsavedChanges;
if (self.hasUnsavedChanges) {
[self backButtonPressed];
}
return result;
}
@end
NS_ASSUME_NONNULL_END

View file

@ -827,10 +827,7 @@ NS_ASSUME_NONNULL_BEGIN
updateGroupViewController.conversationSettingsViewDelegate = self.conversationSettingsViewDelegate;
updateGroupViewController.thread = (TSGroupThread *)self.thread;
updateGroupViewController.mode = mode;
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:updateGroupViewController];
[self presentViewController:navigationController animated:YES completion:nil];
[self.navigationController pushViewController:updateGroupViewController animated:YES];
}
- (void)presentContactViewController

View file

@ -0,0 +1,24 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
// Any view controller which wants to be able cancel back button
// presses and back gestures should implement this protocol.
@protocol OWSNavigationView <NSObject>
// shouldCancelNavigationBack will be called if the back button was pressed or
// if a back gesture was performed but not if the view is popped programmatically.
- (BOOL)shouldCancelNavigationBack;
@end
#pragma mark -
// This navigation controller subclass should be used anywhere we might
// want to cancel back button presses or back gestures due to, for example,
// unsaved changes.
@interface OWSNavigationController : UINavigationController
@end

View file

@ -0,0 +1,76 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSNavigationController.h"
// We use a category to expose UINavigationController's private
// UINavigationBarDelegate methods.
@interface UINavigationController (OWSNavigationController) <UINavigationBarDelegate>
@end
#pragma mark -
@interface OWSNavigationController () <UIGestureRecognizerDelegate>
@end
#pragma mark -
@implementation OWSNavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
self.interactivePopGestureRecognizer.delegate = self;
}
#pragma mark - UINavigationBarDelegate
// All UINavigationController serve as the UINavigationBarDelegate for their navbar.
// We override shouldPopItem: in order to cancel some back button presses - for example,
// if a view has unsaved changes.
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
OWSAssert(self.interactivePopGestureRecognizer.delegate == self);
UIViewController *topViewController = self.topViewController;
// wasBackButtonClicked is YES if the back button was pressed but not
// if a back gesture was performed or if the view is popped programmatically.
BOOL wasBackButtonClicked = topViewController.navigationItem == item;
BOOL result = YES;
if (wasBackButtonClicked) {
if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) {
id<OWSNavigationView> navigationView = (id<OWSNavigationView>)topViewController;
result = ![navigationView shouldCancelNavigationBack];
}
}
// If we're not going to cancel the pop/back, we need to call the super
// implementation since it has important side effects.
if (result) {
result = [super navigationBar:navigationBar shouldPopItem:item];
OWSAssert(result);
}
return result;
}
#pragma mark - UIGestureRecognizerDelegate
// We serve as the UIGestureRecognizerDelegate of the interactivePopGestureRecognizer
// in order to cancel some "back" gestures - for example,
// if a view has unsaved changes.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UIViewController *topViewController = self.topViewController;
if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) {
id<OWSNavigationView> navigationView = (id<OWSNavigationView>)topViewController;
return ![navigationView shouldCancelNavigationBack];
} else {
return YES;
}
}
@end

View file

@ -6,8 +6,18 @@
NS_ASSUME_NONNULL_BEGIN
@class SignalsViewController;
@interface ProfileViewController : OWSTableViewController
- (instancetype)init NS_UNAVAILABLE;
+ (BOOL)shouldDisplayProfileViewOnLaunch;
+ (void)presentForAppSettings:(UINavigationController *)navigationController;
+ (void)presentForRegistration:(UINavigationController *)navigationController;
+ (void)presentForUpgradeOrNag:(SignalsViewController *)presentingController;
@end
NS_ASSUME_NONNULL_END

View file

@ -3,17 +3,32 @@
//
#import "ProfileViewController.h"
#import "AppDelegate.h"
#import "AvatarViewHelper.h"
#import "OWSNavigationController.h"
#import "OWSProfileManager.h"
#import "Signal-Swift.h"
#import "SignalsNavigationController.h"
#import "SignalsViewController.h"
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIView+OWS.h"
#import "UIViewController+OWS.h"
#import <SignalServiceKit/NSDate+OWS.h>
#import <SignalServiceKit/TSStorageManager.h>
NS_ASSUME_NONNULL_BEGIN
@interface ProfileViewController () <UITextFieldDelegate, AvatarViewHelperDelegate>
typedef NS_ENUM(NSInteger, ProfileViewMode) {
ProfileViewMode_AppSettings = 0,
ProfileViewMode_Registration,
ProfileViewMode_UpgradeOrNag,
};
NSString *const kProfileView_Collection = @"kProfileView_Collection";
NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDate";
@interface ProfileViewController () <UITextFieldDelegate, AvatarViewHelperDelegate, OWSNavigationView>
@property (nonatomic, readonly) AvatarViewHelper *avatarViewHelper;
@ -29,12 +44,32 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) BOOL hasUnsavedChanges;
@property (nonatomic) ProfileViewMode profileViewMode;
@end
#pragma mark -
@implementation ProfileViewController
- (instancetype)initWithMode:(ProfileViewMode)profileViewMode
{
self = [super init];
if (!self) {
return self;
}
self.profileViewMode = profileViewMode;
// Use the TSStorageManager.dbReadWriteConnection for consistency with the reads below.
[[[TSStorageManager sharedManager] dbReadWriteConnection] setDate:[NSDate new]
forKey:kProfileView_LastPresentedDate
inCollection:kProfileView_Collection];
return self;
}
- (void)loadView
{
[super loadView];
@ -42,8 +77,6 @@ NS_ASSUME_NONNULL_BEGIN
self.view.backgroundColor = [UIColor whiteColor];
[self.navigationController.navigationBar setTranslucent:NO];
self.title = NSLocalizedString(@"PROFILE_VIEW_TITLE", @"Title for the profile view.");
self.navigationItem.leftBarButtonItem =
[self createOWSBackButtonWithTarget:self selector:@selector(backButtonPressed:)];
_avatarViewHelper = [AvatarViewHelper new];
_avatarViewHelper.delegate = self;
@ -51,6 +84,7 @@ NS_ASSUME_NONNULL_BEGIN
_avatar = [OWSProfileManager.sharedManager localProfileAvatarImage];
[self createViews];
[self updateNavigationItem];
}
- (void)createViews
@ -162,13 +196,18 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Event Handling
- (void)backButtonPressed:(id)sender
- (void)backOrSkipButtonPressed
{
[self leaveViewCheckingForUnsavedChanges];
}
- (void)leaveViewCheckingForUnsavedChanges
{
[self.nameTextField resignFirstResponder];
if (!self.hasUnsavedChanges) {
// If user made no changes, return to conversation settings view.
[self.navigationController popViewControllerAnimated:YES];
[self profileCompletedOrSkipped];
return;
}
@ -185,7 +224,7 @@ NS_ASSUME_NONNULL_BEGIN
@"The label for the 'discard' button in alerts and action sheets.")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
[self.navigationController popViewControllerAnimated:YES];
[self profileCompletedOrSkipped];
}]];
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
@ -204,14 +243,42 @@ NS_ASSUME_NONNULL_BEGIN
{
_hasUnsavedChanges = hasUnsavedChanges;
if (hasUnsavedChanges) {
self.navigationItem.rightBarButtonItem = (self.hasUnsavedChanges
? [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_GROUP_UPDATE_BUTTON",
@"The title for the 'update group' button.")
style:UIBarButtonItemStylePlain
target:self
action:@selector(updatePressed)]
: nil);
[self updateNavigationItem];
}
- (void)updateNavigationItem
{
// The navigation bar is hidden in the registration workflow.
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
// Always display a left item to leave the view without making changes.
// This might be a "back", "skip" or "cancel" button depending on the
// context.
switch (self.profileViewMode) {
case ProfileViewMode_AppSettings:
break;
case ProfileViewMode_UpgradeOrNag:
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:@selector(backOrSkipButtonPressed)];
break;
case ProfileViewMode_Registration:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(@"NAVIGATION_ITEM_SKIP_BUTTON", @"A button to skip a view.")
style:UIBarButtonItemStylePlain
target:self
action:@selector(backOrSkipButtonPressed)];
break;
}
if (self.hasUnsavedChanges) {
// If we have a unsaved changes, right item should be a "save" button.
self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:@selector(updatePressed)];
}
}
@ -239,8 +306,7 @@ NS_ASSUME_NONNULL_BEGIN
success:^{
[alertController dismissViewControllerAnimated:NO
completion:^{
[weakSelf.navigationController
popViewControllerAnimated:YES];
[weakSelf updateProfileCompleted];
}];
}
failure:^{
@ -265,6 +331,38 @@ NS_ASSUME_NONNULL_BEGIN
return [self.nameTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
- (void)updateProfileCompleted
{
[self profileCompletedOrSkipped];
}
- (void)profileCompletedOrSkipped
{
// Dismiss this view.
switch (self.profileViewMode) {
case ProfileViewMode_AppSettings:
[self.navigationController popViewControllerAnimated:YES];
break;
case ProfileViewMode_Registration:
[self showHomeView];
break;
case ProfileViewMode_UpgradeOrNag:
[self dismissViewControllerAnimated:YES completion:nil];
break;
}
}
- (void)showHomeView
{
SignalsViewController *homeView = [SignalsViewController new];
homeView.newlyRegisteredUser = YES;
SignalsNavigationController *navigationController =
[[SignalsNavigationController alloc] initWithRootViewController:homeView];
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.window.rootViewController = navigationController;
OWSAssert([navigationController.topViewController isKindOfClass:[SignalsViewController class]]);
}
#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField
@ -313,6 +411,53 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - AvatarViewHelperDelegate
+ (BOOL)shouldDisplayProfileViewOnLaunch
{
// Only nag until the user sets a profile _name_. Profile names are
// recommended; profile avatars are optional.
if ([OWSProfileManager sharedManager].localProfileName.length > 0) {
return NO;
}
// Use the TSStorageManager.dbReadWriteConnection for consistency with the writes above.
NSTimeInterval kProfileNagFrequency = kDayInterval * 30;
NSDate *_Nullable lastPresentedDate =
[[[TSStorageManager sharedManager] dbReadWriteConnection] dateForKey:kProfileView_LastPresentedDate
inCollection:kProfileView_Collection];
return (!lastPresentedDate || fabs([lastPresentedDate timeIntervalSinceNow]) > kProfileNagFrequency);
}
+ (void)presentForAppSettings:(UINavigationController *)navigationController
{
OWSAssert(navigationController);
OWSAssert([navigationController isKindOfClass:[OWSNavigationController class]]);
ProfileViewController *vc = [[ProfileViewController alloc] initWithMode:ProfileViewMode_AppSettings];
[navigationController pushViewController:vc animated:YES];
}
+ (void)presentForRegistration:(UINavigationController *)navigationController
{
OWSAssert(navigationController);
OWSAssert([navigationController isKindOfClass:[OWSNavigationController class]]);
ProfileViewController *vc = [[ProfileViewController alloc] initWithMode:ProfileViewMode_Registration];
[navigationController pushViewController:vc animated:YES];
}
+ (void)presentForUpgradeOrNag:(SignalsViewController *)presentingController
{
OWSAssert(presentingController);
ProfileViewController *vc = [[ProfileViewController alloc] initWithMode:ProfileViewMode_UpgradeOrNag];
OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:vc];
[presentingController presentTopLevelModalViewController:navigationController
animateDismissal:YES
animatePresentation:YES];
}
#pragma mark - AvatarViewHelperDelegate
- (NSString *)avatarActionSheetTitle
{
return NSLocalizedString(
@ -347,6 +492,17 @@ NS_ASSUME_NONNULL_BEGIN
self.avatar = nil;
}
#pragma mark - OWSNavigationView
- (BOOL)shouldCancelNavigationBack
{
BOOL result = self.hasUnsavedChanges;
if (result) {
[self backOrSkipButtonPressed];
}
return result;
}
#pragma mark - Logging
+ (NSString *)tag

View file

@ -2,8 +2,8 @@
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "OWSNavigationController.h"
@interface SignalsNavigationController : UINavigationController
@interface SignalsNavigationController : OWSNavigationController
@end

View file

@ -10,6 +10,8 @@
#import "MessagesViewController.h"
#import "NSDate+millisecondTimeStamp.h"
#import "OWSContactsManager.h"
#import "OWSNavigationController.h"
#import "ProfileViewController.h"
#import "PropertyListPreferences.h"
#import "PushManager.h"
#import "Signal-Swift.h"
@ -49,6 +51,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
@property (nonatomic) BOOL isViewVisible;
@property (nonatomic) BOOL isAppInBackground;
@property (nonatomic) BOOL shouldObserveDBModifications;
@property (nonatomic) BOOL hasBeenPresented;
// Dependencies
@ -307,7 +310,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
- (void)settingsButtonPressed:(id)sender {
AppSettingsViewController *vc = [AppSettingsViewController new];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:vc];
[self presentViewController:navigationController animated:YES completion:nil];
}
@ -351,8 +354,8 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
//
// We just want to make sure contact access is *complete* before showing the compose
// screen to avoid flicker.
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:viewController];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:viewController];
[self presentTopLevelModalViewController:navigationController animateDismissal:YES animatePresentation:YES];
}];
}
@ -528,7 +531,11 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
completion:^{
[self markAllUpgradeExperiencesAsSeen];
}];
} else if (!self.hasBeenPresented && [ProfileViewController shouldDisplayProfileViewOnLaunch]) {
[ProfileViewController presentForUpgradeOrNag:self];
}
self.hasBeenPresented = YES;
}
- (void)tableViewSetUp {

View file

@ -10,6 +10,7 @@
#import "ContactsViewHelper.h"
#import "Environment.h"
#import "OWSContactsManager.h"
#import "OWSNavigationController.h"
#import "OWSTableViewController.h"
#import "Signal-Swift.h"
#import "SignalKeyingStorage.h"
@ -33,7 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
AvatarViewHelperDelegate,
AddToGroupViewControllerDelegate,
OWSTableViewControllerDelegate,
UINavigationControllerDelegate>
UINavigationControllerDelegate,
OWSNavigationView>
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@ -103,8 +105,6 @@ NS_ASSUME_NONNULL_BEGIN
self.previousMemberRecipientIds = [NSSet setWithArray:self.thread.groupModel.groupMemberIds];
self.title = NSLocalizedString(@"EDIT_GROUP_DEFAULT_TITLE", @"The navbar title for the 'update group' view.");
self.navigationItem.leftBarButtonItem =
[self createOWSBackButtonWithTarget:self selector:@selector(backButtonPressed:)];
// First section.
@ -409,13 +409,13 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Event Handling
- (void)backButtonPressed:(id)sender
- (void)backButtonPressed
{
[self.groupNameTextField resignFirstResponder];
if (!self.hasUnsavedChanges) {
// If user made no changes, return to conversation settings view.
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popViewControllerAnimated:YES];
return;
}
@ -441,7 +441,7 @@ NS_ASSUME_NONNULL_BEGIN
@"The label for the 'don't save' button in action sheets.")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popViewControllerAnimated:YES];
}]];
[self presentViewController:controller animated:YES completion:nil];
}
@ -528,6 +528,17 @@ NS_ASSUME_NONNULL_BEGIN
return [self.memberRecipientIds containsObject:recipientId];
}
#pragma mark - OWSNavigationView
- (BOOL)shouldCancelNavigationBack
{
BOOL result = self.hasUnsavedChanges;
if (result) {
[self backButtonPressed];
}
return result;
}
@end
NS_ASSUME_NONNULL_END

View file

@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (UIBarButtonItem *)createOWSBackButton;
- (UIBarButtonItem *)createOWSBackButtonWithTarget:(id)target selector:(SEL)selector;
@end
NS_ASSUME_NONNULL_END

View file

@ -861,6 +861,9 @@
/* An explanation of the consequences of muting a thread. */
"MUTE_BEHAVIOR_EXPLANATION" = "You will not receive notifications for muted conversations.";
/* A button to skip a view. */
"NAVIGATION_ITEM_SKIP_BUTTON" = "Skip";
/* No comment provided by engineer. */
"NETWORK_ERROR_RECOVERY" = "Please check you're online and try again.";