Wait a week before nagging when a new release comes out

This commit is contained in:
Michael Kirk 2018-08-07 18:55:24 -06:00
parent 63c94efc86
commit 9662b3cb1e
9 changed files with 240 additions and 147 deletions

View File

@ -32,7 +32,6 @@ end
target 'Signal' do
shared_pods
pod 'ATAppUpdater', :inhibit_warnings => true
pod 'SSZipArchive', :inhibit_warnings => true
target 'SignalTests' do

View File

@ -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

@ -1 +1 @@
Subproject commit 5da11dee08c2cc8864ea03b1489bd8898d28dd4e
Subproject commit 73bf1779e0298cbc28c0b93d908bae0aa1f44bbc

View File

@ -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 */,

View File

@ -3,7 +3,6 @@
//
#import "AppDelegate.h"
#import "AppUpdateNag.h"
#import "CodeVerificationViewController.h"
#import "DebugLogger.h"
#import "HomeViewController.h"

View File

@ -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"

View File

@ -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

View File

@ -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

View 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)
}
}