From 0bd80c91bea2e78ee00a4a1b23a1550b3dbb058e Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Tue, 7 Jan 2014 21:47:48 +0100 Subject: [PATCH] Added button to expired page (and alert) that lets the user check for a new version - Added option to disable the option via new `disableUpdateCheckOptionWhenExpired` property --- Classes/BITHockeyBaseManagerPrivate.h | 1 + Classes/BITUpdateManager.h | 18 ++++++ Classes/BITUpdateManager.m | 87 ++++++++++++++++++--------- 3 files changed, 77 insertions(+), 29 deletions(-) diff --git a/Classes/BITHockeyBaseManagerPrivate.h b/Classes/BITHockeyBaseManagerPrivate.h index 23f784a92e..6c557f92f1 100644 --- a/Classes/BITHockeyBaseManagerPrivate.h +++ b/Classes/BITHockeyBaseManagerPrivate.h @@ -48,6 +48,7 @@ - (NSString *)executableUUID; // UI helpers +- (UIWindow *)findVisibleWindow; - (UINavigationController *)customNavigationControllerWithRootViewController:(UIViewController *)viewController presentationStyle:(UIModalPresentationStyle)presentationStyle; - (void)showView:(UIViewController *)viewController; diff --git a/Classes/BITUpdateManager.h b/Classes/BITUpdateManager.h index 6013fe1a4a..959804f1c6 100644 --- a/Classes/BITUpdateManager.h +++ b/Classes/BITUpdateManager.h @@ -200,12 +200,30 @@ typedef NS_ENUM (NSUInteger, BITUpdateSetting) { When running the app from the App Store, this setting is ignored. *Default*: nil + @see disableUpdateCheckOptionWhenExpired @see [BITUpdateManagerDelegate shouldDisplayExpiryAlertForUpdateManager:] @see [BITUpdateManagerDelegate didDisplayExpiryAlertForUpdateManager:] @warning This only works when using Ad-Hoc provisioning profiles! */ @property (nonatomic, strong) NSDate *expiryDate; +/** + Disable the update check button from expiry screen or alerts + + If do not want your users to be able to check for updates once a version is expired, + then enable this property. + + If this is not enabled, the users will be able to check for updates and install them + if any is available for the current device. + + *Default*: NO + @see expiryDate + @see [BITUpdateManagerDelegate shouldDisplayExpiryAlertForUpdateManager:] + @see [BITUpdateManagerDelegate didDisplayExpiryAlertForUpdateManager:] + @warning This only works when using Ad-Hoc provisioning profiles! +*/ +@property (nonatomic) BOOL disableUpdateCheckOptionWhenExpired; + ///----------------------------------------------------------------------------- /// @name User Interface diff --git a/Classes/BITUpdateManager.m b/Classes/BITUpdateManager.m index 6deabd1640..71c82a0d81 100644 --- a/Classes/BITUpdateManager.m +++ b/Classes/BITUpdateManager.m @@ -74,6 +74,9 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { NSNumber *_versionID; NSString *_versionUUID; NSString *_uuid; + + NSString *_blockingScreenMessage; + NSDate *_lastUpdateCheckFromBlockingScreen; } @@ -191,7 +194,9 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { if (shouldShowDefaultAlert) { NSString *appName = bit_appName(BITHockeyLocalizedString(@"HockeyAppNamePlaceholder")); - [self showBlockingScreen:[NSString stringWithFormat:BITHockeyLocalizedString(@"UpdateExpired"), appName] image:@"authorize_denied.png"]; + if (!_blockingScreenMessage) + _blockingScreenMessage = [NSString stringWithFormat:BITHockeyLocalizedString(@"UpdateExpired"), appName]; + [self showBlockingScreen:_blockingScreenMessage image:@"authorize_denied.png"]; if (self.delegate != nil && [self.delegate respondsToSelector:@selector(didDisplayExpiryAlertForUpdateManager:)]) { [self.delegate didDisplayExpiryAlertForUpdateManager:self]; @@ -377,29 +382,6 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { [[NSUserDefaults standardUserDefaults] synchronize]; } -#pragma mark - Window Helper - -- (UIWindow *)findVisibleWindow { - UIWindow *visibleWindow = nil; - - // if the rootViewController property (available >= iOS 4.0) of the main window is set, we present the modal view controller on top of the rootViewController - NSArray *windows = [[UIApplication sharedApplication] windows]; - for (UIWindow *window in windows) { - if (!window.hidden && !visibleWindow) { - visibleWindow = window; - } - if ([UIWindow instancesRespondToSelector:@selector(rootViewController)]) { - if ([window rootViewController]) { - visibleWindow = window; - BITHockeyLog(@"INFO: UIWindow with rootViewController found: %@", visibleWindow); - break; - } - } - } - - return visibleWindow; -} - #pragma mark - Init @@ -515,7 +497,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { self.barStyle = UIBarStyleBlack; BITUpdateViewController *updateViewController = [self hockeyViewController:YES]; - if ([self hasNewerMandatoryVersion]) { + if ([self hasNewerMandatoryVersion] || [self expiryDateReached]) { [updateViewController setMandatoryUpdate: YES]; } [self showView:updateViewController]; @@ -580,9 +562,19 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { [self.blockingView addSubview:imageView]; } + if (!self.disableUpdateCheckOptionWhenExpired) { + UIButton *checkForUpdateButton = [UIButton buttonWithType:kBITButtonTypeSystem]; + checkForUpdateButton.frame = CGRectMake((frame.size.width - 140) / 2.f, frame.size.height - 100, 140, 25); + [checkForUpdateButton setTitle:BITHockeyLocalizedString(@"UpdateButtonCheck") forState:UIControlStateNormal]; + [checkForUpdateButton addTarget:self + action:@selector(checkForUpdateForExpiredVersion) + forControlEvents:UIControlEventTouchUpInside]; + [self.blockingView addSubview:checkForUpdateButton]; + } + if (message != nil) { frame.origin.x = 20; - frame.origin.y = frame.size.height - 140; + frame.origin.y = frame.size.height - 180; frame.size.width -= 40; frame.size.height = 70; @@ -599,6 +591,16 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { [visibleWindow addSubview:self.blockingView]; } +- (void)checkForUpdateForExpiredVersion { + if (!self.checkInProgress) { + + if (!_lastUpdateCheckFromBlockingScreen || + abs([NSDate timeIntervalSinceReferenceDate] - [_lastUpdateCheckFromBlockingScreen timeIntervalSinceReferenceDate]) > 60) { + _lastUpdateCheckFromBlockingScreen = [NSDate date]; + [self checkForUpdateShowFeedback:NO]; + } + } +} // nag the user with neverending alerts if we cannot find out the window for presenting the covering sheet - (void)alertFallback:(NSString *)message { @@ -608,6 +610,11 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { cancelButtonTitle:BITHockeyLocalizedString(@"HockeyOK") otherButtonTitles:nil ]; + + if (!self.disableUpdateCheckOptionWhenExpired && [message isEqualToString:_blockingScreenMessage]) { + [alertView addButtonWithTitle:BITHockeyLocalizedString(@"UpdateButtonCheck")]; + } + [alertView setTag:BITUpdateAlertViewTagNeverEndingAlertView]; [alertView show]; } @@ -813,7 +820,13 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { self.receivedData = nil; self.urlConnection = nil; self.checkInProgress = NO; - [self reportError:error]; + if ([self expiryDateReached]) { + if (!self.blockingView) { + [self alertFallback:_blockingScreenMessage]; + } + } else { + [self reportError:error]; + } } // api call returned, parsing @@ -910,11 +923,16 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { } _showFeedback = NO; } - } else { + } else if (![self expiryDateReached]) { [self reportError:[NSError errorWithDomain:kBITUpdateErrorDomain code:BITUpdateAPIServerReturnedEmptyResponse userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Server returned an empty response.", NSLocalizedDescriptionKey, nil]]]; } + + if (!_updateAlertShowing && [self expiryDateReached] && !self.blockingView) { + [self alertFallback:_blockingScreenMessage]; + } + self.receivedData = nil; self.urlConnection = nil; } @@ -1021,17 +1039,28 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { // invoke the selected action from the action sheet for a location element - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if ([alertView tag] == BITUpdateAlertViewTagNeverEndingAlertView) { - [self alertFallback:[alertView message]]; + if (buttonIndex == 1) { + [self checkForUpdateForExpiredVersion]; + } else { + [self alertFallback:_blockingScreenMessage]; + } return; } _updateAlertShowing = NO; if (buttonIndex == [alertView firstOtherButtonIndex]) { // YES button has been clicked + if (self.blockingView) { + [self.blockingView removeFromSuperview]; + } [self showUpdateView]; } else if (buttonIndex == [alertView firstOtherButtonIndex] + 1) { // YES button has been clicked (void)[self initiateAppDownload]; + } else { + if ([self expiryDateReached] && !self.blockingView) { + [self alertFallback:_blockingScreenMessage]; + } } }