mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Wait a week before nagging when a new release comes out
This commit is contained in:
parent
63c94efc86
commit
9662b3cb1e
1
Podfile
1
Podfile
|
@ -32,7 +32,6 @@ end
|
|||
|
||||
target 'Signal' do
|
||||
shared_pods
|
||||
pod 'ATAppUpdater', :inhibit_warnings => true
|
||||
pod 'SSZipArchive', :inhibit_warnings => true
|
||||
|
||||
target 'SignalTests' do
|
||||
|
|
|
@ -14,7 +14,6 @@ PODS:
|
|||
- AFNetworking/Serialization (3.2.1)
|
||||
- AFNetworking/UIKit (3.2.1):
|
||||
- AFNetworking/NSURLSession
|
||||
- ATAppUpdater (2.0)
|
||||
- AxolotlKit (0.9.0):
|
||||
- CocoaLumberjack
|
||||
- Curve25519Kit (~> 2.1.0)
|
||||
|
@ -137,7 +136,6 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- AFNetworking
|
||||
- ATAppUpdater
|
||||
- AxolotlKit (from `https://github.com/signalapp/SignalProtocolKit.git`)
|
||||
- Curve25519Kit (from `https://github.com/signalapp/Curve25519Kit`)
|
||||
- GRKOpenSSLFramework (from `https://github.com/signalapp/GRKOpenSSLFramework`)
|
||||
|
@ -155,7 +153,6 @@ DEPENDENCIES:
|
|||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- AFNetworking
|
||||
- ATAppUpdater
|
||||
- CocoaLumberjack
|
||||
- libPhoneNumber-iOS
|
||||
- Mantle
|
||||
|
@ -213,7 +210,6 @@ CHECKOUT OPTIONS:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057
|
||||
ATAppUpdater: a9f7027060959d47e58733d3b48f6b9a28cb8de1
|
||||
AxolotlKit: 07bd978ea931d113939de88d3d2d354896680ceb
|
||||
CocoaLumberjack: db7cc9e464771f12054c22ff6947c5a58d43a0fd
|
||||
Curve25519Kit: 76d0859ecb34704f7732847812363f83b23a6a59
|
||||
|
@ -233,6 +229,6 @@ SPEC CHECKSUMS:
|
|||
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
|
||||
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
|
||||
|
||||
PODFILE CHECKSUM: 0c3d5978b54712391b5b90835b9554277b07fa23
|
||||
PODFILE CHECKSUM: cb4f38eaa6b1bdf86cfe440ef964c628e6d8321d
|
||||
|
||||
COCOAPODS: 1.5.3
|
||||
|
|
2
Pods
2
Pods
|
@ -1 +1 @@
|
|||
Subproject commit 5da11dee08c2cc8864ea03b1489bd8898d28dd4e
|
||||
Subproject commit 73bf1779e0298cbc28c0b93d908bae0aa1f44bbc
|
|
@ -209,7 +209,6 @@
|
|||
34C82E5120F8E1F300E9688D /* Theme.h in Headers */ = {isa = PBXBuildFile; fileRef = 34C82E4F20F8E1F000E9688D /* Theme.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34C82E5220F8E1F300E9688D /* Theme.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C82E5020F8E1F100E9688D /* Theme.m */; };
|
||||
34CA631B2097806F00E526A0 /* OWSContactShareView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CA631A2097806E00E526A0 /* OWSContactShareView.m */; };
|
||||
34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; };
|
||||
34CE88E71F2FB9A10098030F /* ProfileViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CE88E61F2FB9A10098030F /* ProfileViewController.m */; };
|
||||
34CF0787203E6B78005C4D61 /* busy_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */; };
|
||||
34CF0788203E6B78005C4D61 /* ringback_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0784203E6B77005C4D61 /* ringback_tone_ansi.caf */; };
|
||||
|
@ -440,6 +439,7 @@
|
|||
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5F26820F7D060004D1B42 /* MessageActions.swift */; };
|
||||
4CC0B59C20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */; };
|
||||
4CC1ECF9211A47CE00CC13BE /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC1ECFA211A553000CC13BE /* AppUpdateNag.swift */; };
|
||||
70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; };
|
||||
768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; };
|
||||
76C87F19181EFCE600C4ACAB /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; };
|
||||
|
@ -868,8 +868,6 @@
|
|||
34CA1C281F7164F700E51C51 /* MediaMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaMessageView.swift; sourceTree = "<group>"; };
|
||||
34CA63192097806E00E526A0 /* OWSContactShareView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactShareView.h; sourceTree = "<group>"; };
|
||||
34CA631A2097806E00E526A0 /* OWSContactShareView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactShareView.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>"; };
|
||||
34CE88E51F2FB9A10098030F /* ProfileViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileViewController.h; sourceTree = "<group>"; };
|
||||
34CE88E61F2FB9A10098030F /* ProfileViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProfileViewController.m; sourceTree = "<group>"; };
|
||||
34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = busy_tone_ansi.caf; path = Signal/AudioFiles/busy_tone_ansi.caf; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -1118,6 +1116,7 @@
|
|||
4CB5F26820F7D060004D1B42 /* MessageActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions.swift; sourceTree = "<group>"; };
|
||||
4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationConfigurationSyncOperation.swift; sourceTree = "<group>"; };
|
||||
4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
4CC1ECFA211A553000CC13BE /* AppUpdateNag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateNag.swift; sourceTree = "<group>"; };
|
||||
4CFF4C0920F55BBA005DA313 /* MenuActionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuActionsViewController.swift; sourceTree = "<group>"; };
|
||||
69349DE607F5BA6036C9AC60 /* Pods-SignalShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
70377AAA1918450100CAF501 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
|
||||
|
@ -2174,8 +2173,6 @@
|
|||
76EB04C818170B33006006FC /* util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34CCAF361F0C0599004084F4 /* AppUpdateNag.h */,
|
||||
34CCAF371F0C0599004084F4 /* AppUpdateNag.m */,
|
||||
B90418E4183E9DD40038554A /* DateUtil.h */,
|
||||
B90418E5183E9DD40038554A /* DateUtil.m */,
|
||||
76EB04EA18170B33006006FC /* FunctionalUtil.h */,
|
||||
|
@ -2206,6 +2203,7 @@
|
|||
34E5DC8120D8050D00C08145 /* RegistrationUtils.m */,
|
||||
4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */,
|
||||
FCFA64B11A24F29E0007FB87 /* UI Categories */,
|
||||
4CC1ECFA211A553000CC13BE /* AppUpdateNag.swift */,
|
||||
);
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2991,7 +2989,6 @@
|
|||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-Signal/Pods-Signal-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/ATAppUpdater/ATAppUpdater.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/AxolotlKit/AxolotlKit.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Curve25519Kit/Curve25519Kit.framework",
|
||||
|
@ -3014,7 +3011,6 @@
|
|||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ATAppUpdater.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AxolotlKit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Curve25519Kit.framework",
|
||||
|
@ -3288,7 +3284,6 @@
|
|||
34386A51207D0C01009F5D9C /* HomeViewController.m in Sources */,
|
||||
34D1F0A91F867BFC0066283D /* ConversationViewCell.m in Sources */,
|
||||
4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */,
|
||||
34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */,
|
||||
EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */,
|
||||
45CD81EF1DC030E7004C9430 /* SyncPushTokensJob.swift in Sources */,
|
||||
34D2CCE0206939B400CB1A14 /* DebugUIMessagesAssetLoader.m in Sources */,
|
||||
|
@ -3356,6 +3351,7 @@
|
|||
34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */,
|
||||
457C87B82032645C008D52D6 /* DebugUINotifications.swift in Sources */,
|
||||
4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */,
|
||||
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */,
|
||||
340FC8D0205BF2FA007AEB0F /* OWSBackupIO.m in Sources */,
|
||||
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
|
||||
4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "AppUpdateNag.h"
|
||||
#import "CodeVerificationViewController.h"
|
||||
#import "DebugLogger.h"
|
||||
#import "HomeViewController.h"
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#import "PrivacySettingsTableViewController.h"
|
||||
#import "ProfileViewController.h"
|
||||
#import "PushManager.h"
|
||||
#import "RegistrationViewController.h"
|
||||
#import "RemoteVideoView.h"
|
||||
#import "SignalApp.h"
|
||||
#import "UIViewController+Permissions.h"
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
@interface AppUpdateNag : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
- (void)showAppUpgradeNagIfNecessary;
|
||||
|
||||
@end
|
|
@ -1,118 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppUpdateNag.h"
|
||||
#import "RegistrationViewController.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import <ATAppUpdater/ATAppUpdater.h>
|
||||
#import <SignalServiceKit/NSDate+OWS.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
|
||||
NSString *const OWSPrimaryStorageAppUpgradeNagCollection = @"TSStorageManagerAppUpgradeNagCollection";
|
||||
NSString *const OWSPrimaryStorageAppUpgradeNagDate = @"TSStorageManagerAppUpgradeNagDate";
|
||||
|
||||
@interface AppUpdateNag () <ATAppUpdaterDelegate>
|
||||
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation AppUpdateNag
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static AppUpdateNag *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[self alloc] initDefault];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)initDefault
|
||||
{
|
||||
OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
|
||||
|
||||
return [self initWithPrimaryStorage:primaryStorage];
|
||||
}
|
||||
|
||||
- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
OWSAssert(primaryStorage);
|
||||
|
||||
_dbConnection = primaryStorage.newDatabaseConnection;
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)showAppUpgradeNagIfNecessary
|
||||
{
|
||||
if (CurrentAppContext().isRunningTests) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only show nag if we are "at rest" in the home view or registration view without any
|
||||
// alerts or dialogs showing.
|
||||
UIViewController *frontmostViewController =
|
||||
[UIApplication sharedApplication].frontmostViewController;
|
||||
OWSAssert(frontmostViewController);
|
||||
BOOL canPresent = ([frontmostViewController isKindOfClass:[HomeViewController class]] ||
|
||||
[frontmostViewController isKindOfClass:[RegistrationViewController class]]);
|
||||
if (!canPresent) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDate *lastNagDate = [self.dbConnection dateForKey:OWSPrimaryStorageAppUpgradeNagDate
|
||||
inCollection:OWSPrimaryStorageAppUpgradeNagCollection];
|
||||
const NSTimeInterval kNagFrequency = kDayInterval * 14;
|
||||
BOOL canNag = (!lastNagDate || fabs(lastNagDate.timeIntervalSinceNow) > kNagFrequency);
|
||||
if (!canNag) {
|
||||
return;
|
||||
}
|
||||
|
||||
ATAppUpdater *updater = [ATAppUpdater sharedUpdater];
|
||||
[updater setAlertTitle:NSLocalizedString(
|
||||
@"APP_UPDATE_NAG_ALERT_TITLE", @"Title for the 'new app version available' alert.")];
|
||||
[updater setAlertMessage:NSLocalizedString(@"APP_UPDATE_NAG_ALERT_MESSAGE_FORMAT",
|
||||
@"Message format for the 'new app version available' alert. Embeds: {{The latest app "
|
||||
@"version number.}}.")];
|
||||
[updater setAlertUpdateButtonTitle:NSLocalizedString(@"APP_UPDATE_NAG_ALERT_UPDATE_BUTTON",
|
||||
@"Label for the 'update' button in the 'new app version available' alert.")];
|
||||
[updater setAlertCancelButtonTitle:CommonStrings.cancelButton];
|
||||
[updater setDelegate:self];
|
||||
[updater showUpdateWithConfirmation];
|
||||
}
|
||||
|
||||
#pragma mark - ATAppUpdaterDelegate
|
||||
|
||||
- (void)appUpdaterDidShowUpdateDialog
|
||||
{
|
||||
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||
|
||||
[self.dbConnection setDate:[NSDate new]
|
||||
forKey:OWSPrimaryStorageAppUpgradeNagDate
|
||||
inCollection:OWSPrimaryStorageAppUpgradeNagCollection];
|
||||
}
|
||||
|
||||
- (void)appUpdaterUserDidLaunchAppStore
|
||||
{
|
||||
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
- (void)appUpdaterUserDidCancel
|
||||
{
|
||||
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
@end
|
233
Signal/src/util/AppUpdateNag.swift
Normal file
233
Signal/src/util/AppUpdateNag.swift
Normal file
|
@ -0,0 +1,233 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PromiseKit
|
||||
|
||||
@objc
|
||||
class AppUpdateNag: NSObject {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@objc(sharedInstance)
|
||||
public static let shared: AppUpdateNag = {
|
||||
let versionService = AppStoreVersionService()
|
||||
let nagManager = AppUpdateNag(versionService: versionService)
|
||||
return nagManager
|
||||
}()
|
||||
|
||||
@objc
|
||||
public func showAppUpgradeNagIfNecessary() {
|
||||
|
||||
guard let currentVersion = self.currentVersion else {
|
||||
owsFail("\(self.logTag) in \(#function) currentVersion was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
guard let bundleIdentifier = self.bundleIdentifier else {
|
||||
owsFail("\(self.logTag) in \(#function) bundleIdentifier was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
guard let lookupURL = lookupURL(bundleIdentifier: bundleIdentifier) else {
|
||||
owsFail("\(self.logTag) in \(#function) appStoreURL was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
firstly {
|
||||
self.versionService.fetchLatestVersion(lookupURL: lookupURL)
|
||||
}.then { appStoreRecord -> Void in
|
||||
guard appStoreRecord.version.compare(currentVersion, options: .numeric) == ComparisonResult.orderedDescending else {
|
||||
Logger.debug("\(self.logTag) same old version: \(appStoreRecord)")
|
||||
return
|
||||
}
|
||||
|
||||
Logger.info("\(self.logTag) new version available: \(appStoreRecord)")
|
||||
self.showUpdateNagIfEnoughTimeHasPassed(appStoreRecord: appStoreRecord)
|
||||
}.catch { error in
|
||||
Logger.error("\(self.logTag) in \(#function) failed with error: \(error)")
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
let kUpgradeNagCollection = "TSStorageManagerAppUpgradeNagCollection"
|
||||
let kLastNagDateKey = "TSStorageManagerAppUpgradeNagDate"
|
||||
let kFirstHeardOfNewVersionDateKey = "TSStorageManagerAppUpgradeFirstHeardOfNewVersionDate"
|
||||
|
||||
var dbConnection: YapDatabaseConnection {
|
||||
return OWSPrimaryStorage.shared().dbReadWriteConnection
|
||||
}
|
||||
|
||||
// MARK: Bundle accessors
|
||||
|
||||
var bundle: Bundle {
|
||||
return Bundle.main
|
||||
}
|
||||
|
||||
var currentVersion: String? {
|
||||
return bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
|
||||
}
|
||||
|
||||
var bundleIdentifier: String? {
|
||||
return bundle.bundleIdentifier
|
||||
}
|
||||
|
||||
func lookupURL(bundleIdentifier: String) -> URL? {
|
||||
return URL(string: "https://itunes.apple.com/lookup?bundleId=\(bundleIdentifier)")
|
||||
}
|
||||
|
||||
let versionService: AppStoreVersionService
|
||||
|
||||
required init(versionService: AppStoreVersionService) {
|
||||
self.versionService = versionService
|
||||
super.init()
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
}
|
||||
|
||||
func showUpdateNagIfEnoughTimeHasPassed(appStoreRecord: AppStoreRecord) {
|
||||
guard let firstHeardOfNewVersionDate = self.firstHeardOfNewVersionDate else {
|
||||
self.setFirstHeardOfNewVersionDate(Date())
|
||||
return
|
||||
}
|
||||
|
||||
let intervalBeforeNag = 7 * kDayInterval
|
||||
guard Date() > Date.init(timeInterval: intervalBeforeNag, since: firstHeardOfNewVersionDate) else {
|
||||
Logger.info("\(logTag) in \(#function) firstHeardOfNewVersionDate: \(firstHeardOfNewVersionDate) not nagging for new release yet.")
|
||||
return
|
||||
}
|
||||
|
||||
if let lastNagDate = self.lastNagDate {
|
||||
let intervalBetweenNags = 14 * kDayInterval
|
||||
guard Date() > Date.init(timeInterval: intervalBetweenNags, since: lastNagDate) else {
|
||||
Logger.info("\(logTag) in \(#function) lastNagDate: \(lastNagDate) not nagging again so soon.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Only show nag if we are "at rest" in the home view or registration view without any
|
||||
// alerts or dialogs showing.
|
||||
guard let frontmostViewController = UIApplication.shared.frontmostViewController else {
|
||||
owsFail("\(self.logTag) in \(#function) frontmostViewController was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
switch frontmostViewController {
|
||||
case is HomeViewController, is RegistrationViewController:
|
||||
self.setLastNagDate(Date())
|
||||
self.clearFirstHeardOfNewVersionDate()
|
||||
presentUpgradeNag(appStoreRecord: appStoreRecord)
|
||||
default:
|
||||
Logger.debug("\(logTag) in \(#function) not presenting alert due to frontmostViewController: \(frontmostViewController)")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func presentUpgradeNag(appStoreRecord: AppStoreRecord) {
|
||||
let title = NSLocalizedString("APP_UPDATE_NAG_ALERT_TITLE", comment: "Title for the 'new app version available' alert.")
|
||||
|
||||
let messageFormat = NSLocalizedString("APP_UPDATE_NAG_ALERT_MESSAGE_FORMAT", comment: "Message format for the 'new app version available' alert. Embeds: {{The latest app version number}}")
|
||||
let message = String(format: messageFormat, appStoreRecord.version)
|
||||
let buttonTitle = NSLocalizedString("APP_UPDATE_NAG_ALERT_UPDATE_BUTTON", comment: "Label for the 'update' button in the 'new app version available' alert.")
|
||||
|
||||
OWSAlerts.showAlert(title: title,
|
||||
message: message,
|
||||
buttonTitle: buttonTitle,
|
||||
buttonAction: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.showAppStore(appStoreURL: appStoreRecord.appStoreURL)
|
||||
})
|
||||
}
|
||||
|
||||
func showAppStore(appStoreURL: URL) {
|
||||
Logger.debug("\(logTag) in \(#function)")
|
||||
UIApplication.shared.openURL(appStoreURL)
|
||||
}
|
||||
|
||||
// MARK: Storage
|
||||
|
||||
var firstHeardOfNewVersionDate: Date? {
|
||||
return self.dbConnection.date(forKey: kFirstHeardOfNewVersionDateKey, inCollection: kUpgradeNagCollection)
|
||||
}
|
||||
|
||||
func setFirstHeardOfNewVersionDate(_ date: Date) {
|
||||
self.dbConnection.setDate(date, forKey: kFirstHeardOfNewVersionDateKey, inCollection: kUpgradeNagCollection)
|
||||
}
|
||||
|
||||
func clearFirstHeardOfNewVersionDate() {
|
||||
self.dbConnection.removeObject(forKey: kFirstHeardOfNewVersionDateKey, inCollection: kUpgradeNagCollection)
|
||||
}
|
||||
|
||||
var lastNagDate: Date? {
|
||||
return self.dbConnection.date(forKey: kLastNagDateKey, inCollection: kUpgradeNagCollection)
|
||||
}
|
||||
|
||||
func setLastNagDate(_ date: Date) {
|
||||
self.dbConnection.setDate(date, forKey: kLastNagDateKey, inCollection: kUpgradeNagCollection)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Parsing Structs
|
||||
|
||||
struct AppStoreLookupResultSet: Codable {
|
||||
let resultCount: UInt
|
||||
let results: [AppStoreRecord]
|
||||
}
|
||||
|
||||
struct AppStoreRecord: Codable {
|
||||
let appStoreURL: URL
|
||||
let version: String
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case appStoreURL = "trackViewUrl"
|
||||
case version
|
||||
}
|
||||
}
|
||||
|
||||
class AppStoreVersionService: NSObject {
|
||||
|
||||
// MARK:
|
||||
|
||||
func fetchLatestVersion(lookupURL: URL) -> Promise<AppStoreRecord> {
|
||||
Logger.debug("\(logTag) in \(#function) lookupURL:\(lookupURL)")
|
||||
|
||||
let (promise, fulfill, reject) = Promise<AppStoreRecord>.pending()
|
||||
|
||||
let task = URLSession.ephemeral.dataTask(with: lookupURL) { (data, _, error) in
|
||||
guard let data = data else {
|
||||
owsFail("\(self.logTag) in \(#function) data was unexpectedly nil")
|
||||
reject(OWSErrorMakeUnableToProcessServerResponseError())
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let resultSet = try decoder.decode(AppStoreLookupResultSet.self, from: data)
|
||||
guard let appStoreRecord = resultSet.results.first else {
|
||||
owsFail("\(self.logTag) in \(#function) record was unexpectedly nil")
|
||||
reject(OWSErrorMakeUnableToProcessServerResponseError())
|
||||
return
|
||||
}
|
||||
|
||||
fulfill(appStoreRecord)
|
||||
} catch {
|
||||
reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
|
||||
return promise
|
||||
}
|
||||
}
|
||||
|
||||
extension URLSession {
|
||||
static var ephemeral: URLSession {
|
||||
return URLSession(configuration: .ephemeral)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue