Skip to content

Commit

Permalink
Merge pull request #516 from SwissCovid/feature/remove-appclip
Browse files Browse the repository at this point in the history
Deactivation Fixes
  • Loading branch information
stmitt authored Mar 21, 2022
2 parents 57ea274 + b027e97 commit 6f52f16
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 79 deletions.
55 changes: 0 additions & 55 deletions DP3TApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@
6E5B6979265F6A0500EB0C56 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6E5B6978265F6A0500EB0C56 /* Assets.xcassets */; };
6E5B697C265F6A0500EB0C56 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6E5B697B265F6A0500EB0C56 /* Preview Assets.xcassets */; };
6E5B697F265F6A0500EB0C56 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6E5B697D265F6A0500EB0C56 /* LaunchScreen.storyboard */; };
6E5B6984265F6A0500EB0C56 /* DP3TAppClip.app in Embed App Clips */ = {isa = PBXBuildFile; fileRef = 6E5B6970265F6A0400EB0C56 /* DP3TAppClip.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6E5B698F265F6C6E00EB0C56 /* CrowdNotifierBaseSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6E5B698E265F6C6E00EB0C56 /* CrowdNotifierBaseSDK */; };
6E5B6991265F6C8A00EB0C56 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6E5B6990265F6C8A00EB0C56 /* SnapKit */; };
6E5B6993265F6C8A00EB0C56 /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = 6E5B6992265F6C8A00EB0C56 /* Clibsodium */; };
Expand Down Expand Up @@ -473,7 +472,6 @@
DC746D5A2451DF78009426B1 /* NSHeaderActiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC746D592451DF78009426B1 /* NSHeaderActiveView.swift */; };
DC85DEFD263ADEDA002DF191 /* NSCheckInDetailCheckedOutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC85DEFC263ADEDA002DF191 /* NSCheckInDetailCheckedOutView.swift */; };
DC85DEFE263ADEDA002DF191 /* NSCheckInDetailCheckedOutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC85DEFC263ADEDA002DF191 /* NSCheckInDetailCheckedOutView.swift */; };
DC8CAEED266666CB002D78EF /* DP3TAppClip.app in Embed App Clips */ = {isa = PBXBuildFile; fileRef = 6E5B6970265F6A0400EB0C56 /* DP3TAppClip.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
DC8CAEF226677BC7002D78EF /* UIAlertController+CheckoutAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC8CAEF126677BC6002D78EF /* UIAlertController+CheckoutAlert.swift */; };
DC8CAEF326677BC7002D78EF /* UIAlertController+CheckoutAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC8CAEF126677BC6002D78EF /* UIAlertController+CheckoutAlert.swift */; };
DC9A81AB242CE5E000AD1548 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC9A81A1242CE5E000AD1548 /* Localizable.strings */; };
Expand Down Expand Up @@ -674,54 +672,15 @@
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
6E5B6982265F6A0500EB0C56 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8E81CC8D241FCC7D006F2437 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6E5B696F265F6A0400EB0C56;
remoteInfo = DP3TAppClip;
};
8E81CCAC241FCC7F006F2437 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8E81CC8D241FCC7D006F2437 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8E81CC94241FCC7D006F2437;
remoteInfo = IVC;
};
DC8CAEEE266666CB002D78EF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8E81CC8D241FCC7D006F2437 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6E5B696F265F6A0400EB0C56;
remoteInfo = DP3TAppClip;
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
6E5B6985265F6A0500EB0C56 /* Embed App Clips */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(CONTENTS_FOLDER_PATH)/AppClips";
dstSubfolderSpec = 16;
files = (
6E5B6984265F6A0500EB0C56 /* DP3TAppClip.app in Embed App Clips */,
);
name = "Embed App Clips";
runOnlyForDeploymentPostprocessing = 0;
};
DC8CAEF0266666CB002D78EF /* Embed App Clips */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(CONTENTS_FOLDER_PATH)/AppClips";
dstSubfolderSpec = 16;
files = (
DC8CAEED266666CB002D78EF /* DP3TAppClip.app in Embed App Clips */,
);
name = "Embed App Clips";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
2411CA9E2462ADBE002FB5A9 /* Entitlements.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Entitlements.entitlements; sourceTree = "<group>"; };
242D21D0245C3853005DAEA8 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2210,12 +2169,10 @@
242D2253245C4BD8005DAEA8 /* Frameworks */,
242D2256245C4BD8005DAEA8 /* Resources */,
242D226B245C4BD8005DAEA8 /* ShellScript */,
DC8CAEF0266666CB002D78EF /* Embed App Clips */,
);
buildRules = (
);
dependencies = (
DC8CAEEF266666CB002D78EF /* PBXTargetDependency */,
);
name = DP3TAppCalibration;
packageProductDependencies = (
Expand Down Expand Up @@ -2265,12 +2222,10 @@
8E81CC92241FCC7D006F2437 /* Frameworks */,
8E81CC93241FCC7D006F2437 /* Resources */,
240879652440504500001462 /* Run Script */,
6E5B6985265F6A0500EB0C56 /* Embed App Clips */,
);
buildRules = (
);
dependencies = (
6E5B6983265F6A0500EB0C56 /* PBXTargetDependency */,
);
name = DP3TApp;
packageProductDependencies = (
Expand Down Expand Up @@ -3190,21 +3145,11 @@
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
6E5B6983265F6A0500EB0C56 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6E5B696F265F6A0400EB0C56 /* DP3TAppClip */;
targetProxy = 6E5B6982265F6A0500EB0C56 /* PBXContainerItemProxy */;
};
8E81CCAD241FCC7F006F2437 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8E81CC94241FCC7D006F2437 /* DP3TApp */;
targetProxy = 8E81CCAC241FCC7F006F2437 /* PBXContainerItemProxy */;
};
DC8CAEEF266666CB002D78EF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6E5B696F265F6A0400EB0C56 /* DP3TAppClip */;
targetProxy = DC8CAEEE266666CB002D78EF /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
Expand Down
5 changes: 4 additions & 1 deletion DP3TApp/Logic/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// defer window initialization if app was launched in
// background because of location change
if shouldSetupWindow(application: application, launchOptions: launchOptions) {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
setupWindow()
willAppearAfterColdstart(application, coldStart: true, backgroundTime: 0)
}
Expand Down
10 changes: 8 additions & 2 deletions DP3TApp/Logic/CheckIn/CheckInManager/CheckInManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ class CheckInManager {
switch result {
case let .success(id):
hasCheckedOutOnce = true
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
cc.identifier = id
saveAdditionalInfo(checkIn: cc)
case .failure:
Expand Down Expand Up @@ -122,7 +125,10 @@ class CheckInManager {
switch result {
case let .success(id):
hasCheckedOutOnce = true
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
var intervalCheckIn = CheckIn(identifier: id, qrCode: checkIn.qrCode, checkInTime: arrivalTime, venue: checkIn.venue)
intervalCheckIn.checkOutTime = departureTime
saveAdditionalInfo(checkIn: intervalCheckIn)
Expand Down
11 changes: 9 additions & 2 deletions DP3TApp/Logic/Config/ConfigLoadOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ class ConfigLoadOperation: Operation {
ConfigLoadOperation.presentedConfigForVersion = ConfigManager.appVersion
}
} else if let c = config, c.deactivate {
DispatchQueue.main.sync {
if Thread.isMainThread {
let vc = NSNavigationController(rootViewController: NSDeactivatedInfoViewController())

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.window?.rootViewController? = vc
} else {
DispatchQueue.main.async {
let vc = NSNavigationController(rootViewController: NSDeactivatedInfoViewController())
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.window?.rootViewController? = vc
}
}

TracingManager.shared.setBackgroundRefreshEnabled(false)
Expand All @@ -48,6 +53,8 @@ class ConfigLoadOperation: Operation {
UserStorage.shared.tracingWasActivatedBeforeDeaktivation = true
}

NSLocalPush.shared.cancelAllPendingAndDeliveredNotifications()

UBPushManager.shared.setActive(false)
CheckInManager.shared.cleanUpOldData(maxDaysToKeep: 0)

Expand Down
9 changes: 6 additions & 3 deletions DP3TApp/Logic/Config/ConfigManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ class ConfigManager: NSObject {
}
}

static func shouldLoadConfig(backgroundTask: Bool, url: String?, lastConfigUrl: String?, lastConfigLoad: Date?) -> Bool {
if ConfigManager.currentConfig?.deactivate ?? false {
static func shouldLoadConfig(backgroundTask: Bool, url: String?, lastConfigUrl: String?, lastConfigLoad: Date?, deactivate: Bool?) -> Bool {
if deactivate ?? false {
return true
}
// if the config url was changed (by OS version or app version changing) load config in anycase
Expand Down Expand Up @@ -119,7 +119,8 @@ class ConfigManager: NSObject {
guard Self.shouldLoadConfig(backgroundTask: backgroundTask,
url: request.url?.absoluteString,
lastConfigUrl: Self.lastConfigUrl,
lastConfigLoad: Self.lastConfigLoad) else {
lastConfigLoad: Self.lastConfigLoad,
deactivate: ConfigManager.currentConfig?.deactivate) else {
Logger.log("Skipping config load request and returning from cache", appState: true)
completion(Self.currentConfig)
return
Expand Down Expand Up @@ -220,6 +221,8 @@ class ConfigManager: NSObject {
guard let config = config else { return }

if config.deactivate {
NSLocalPush.shared.cancelAllPendingAndDeliveredNotifications()

if (window?.rootViewController as? UINavigationController)?.visibleViewController is NSDeactivatedInfoViewController {
// The NSDeactivatedInfoViewController is already visible
return
Expand Down
6 changes: 6 additions & 0 deletions DP3TApp/Logic/NSLocalPush.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ protocol UserNotificationCenter {
func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?)
func removeDeliveredNotifications(withIdentifiers identifiers: [String])
func removeAllDeliveredNotifications()
func removeAllPendingNotificationRequests()
func removePendingNotificationRequests(withIdentifiers identifiers: [String])
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
}
Expand Down Expand Up @@ -140,6 +141,11 @@ class NSLocalPush: NSObject, LocalPushProtocol {
center.removePendingNotificationRequests(withIdentifiers: allIdentifier)
}

func cancelAllPendingAndDeliveredNotifications() {
center.removeAllDeliveredNotifications()
center.removeAllPendingNotificationRequests()
}

var now: Date {
.init()
}
Expand Down
5 changes: 4 additions & 1 deletion DP3TApp/Logic/Push/NSPushHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class NSPushHandler: UBPushHandler {
}

// data are updated -> reschedule background task warning triggers
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
}

if self.backgroundTask != .invalid {
Expand Down
9 changes: 7 additions & 2 deletions DP3TApp/Logic/Tracing/DatabaseSyncer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ class DatabaseSyncer {
private var databaseSyncInterval: TimeInterval = 10

func syncDatabaseIfNeeded(completionHandler: ((UIBackgroundFetchResult) -> Void)? = nil) {
let deactivated = (ConfigManager.currentConfig?.deactivate ?? false)
guard !databaseIsSyncing,
UserStorage.shared.hasCompletedOnboarding else {
UserStorage.shared.hasCompletedOnboarding,
!deactivated else {
completionHandler?(.noData)
return
}
Expand Down Expand Up @@ -129,7 +131,10 @@ class DatabaseSyncer {
UIStateManager.shared.syncError = nil
}

NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}

// reload status, user could have been exposed
TracingManager.shared.updateStatus(completion: nil)
Expand Down
16 changes: 11 additions & 5 deletions DP3TApp/Logic/Tracing/TracingManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class TracingManager: NSObject {
}

func requestTracingPermission(completion: @escaping (Error?) -> Void) {
guard #available(iOS 12.5, *), isSupported else { return }
guard #available(iOS 12.5, *), isSupported, ConfigManager.allowTracing else { return }

DP3TTracing.startTracing { result in
switch result {
Expand All @@ -122,7 +122,7 @@ class TracingManager: NSObject {
}

func startTracing(callback: ((TracingEnableResult) -> Void)? = nil) {
guard #available(iOS 12.5, *), isSupported else { return }
guard #available(iOS 12.5, *), isSupported, ConfigManager.allowTracing else { return }
if UserStorage.shared.hasCompletedOnboarding, ConfigManager.allowTracing {
DP3TTracing.startTracing(completionHandler: { result in
switch result {
Expand Down Expand Up @@ -206,7 +206,7 @@ class TracingManager: NSObject {
}

func userHasCompletedOnboarding() {
guard #available(iOS 12.5, *), isSupported else { return }
guard #available(iOS 12.5, *), isSupported, ConfigManager.allowTracing else { return }
if ConfigManager.allowTracing, UserStorage.shared.tracingSettingEnabled {
DP3TTracing.startTracing { result in
switch result {
Expand Down Expand Up @@ -298,7 +298,10 @@ extension TracingManager: DP3TBackgroundHandler {
#endif

// wait another 2 days befor warning
localPush.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
localPush.resetBackgroundTaskWarningTriggers()
}

let queue = OperationQueue()

Expand Down Expand Up @@ -336,7 +339,10 @@ extension TracingManager: DP3TBackgroundHandler {
}

// data are updated -> reschedule background task warning triggers
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}

group.leave()
}
Expand Down
2 changes: 1 addition & 1 deletion DP3TApp/Supporting Files/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>2.3.2</string>
<string>2.4.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>ENAPIVersion</key>
Expand Down
2 changes: 1 addition & 1 deletion DP3TAppClip/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>2.3.2</string>
<string>2.4.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
Expand Down
17 changes: 11 additions & 6 deletions DP3TAppTests/ConfigManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,34 @@ import XCTest
class ConfigManagerTests: XCTestCase {
func testLoadingAfterTimeForeground() {
let lastLoad = Date(timeIntervalSinceNow: -ConfigManager.configForegroundValidityInterval)
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: false, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad))
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: false, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad, deactivate: false))
}

func testDontLoadAfterTimeForeground() {
let lastLoad = Date(timeIntervalSinceNow: -ConfigManager.configForegroundValidityInterval + 1)
XCTAssertFalse(ConfigManager.shouldLoadConfig(backgroundTask: false, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad))
XCTAssertFalse(ConfigManager.shouldLoadConfig(backgroundTask: false, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad, deactivate: false))
}

func testLoadingAfterTimeBackground() {
let lastLoad = Date(timeIntervalSinceNow: -ConfigManager.configBackgroundValidityInterval)
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad))
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad, deactivate: false))
}

func testDontLoadAfterTimeBackground() {
let lastLoad = Date(timeIntervalSinceNow: -ConfigManager.configBackgroundValidityInterval + 1)
XCTAssertFalse(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad))
XCTAssertFalse(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad, deactivate: false))
}

func testLoadConfigAfterUrlChange() {
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "newUrl", lastConfigUrl: "url", lastConfigLoad: .init()))
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "newUrl", lastConfigUrl: "url", lastConfigLoad: .init(), deactivate: false))
}

func testLoadConfigAfterUpdate() {
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "newUrl", lastConfigUrl: nil, lastConfigLoad: .init()))
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "newUrl", lastConfigUrl: nil, lastConfigLoad: .init(), deactivate: false))
}

func testAlwaysLoadConfigAfterDeactivate() {
let lastLoad = Date(timeIntervalSinceNow: -ConfigManager.configBackgroundValidityInterval + 1)
XCTAssert(ConfigManager.shouldLoadConfig(backgroundTask: true, url: "url", lastConfigUrl: "url", lastConfigLoad: lastLoad, deactivate: true))
}
}
4 changes: 4 additions & 0 deletions DP3TAppTests/MockNotificationCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class MockNotificationCenter: UserNotificationCenter {
requests.removeAll()
}

func removeAllPendingNotificationRequests() {
requests.removeAll()
}

func removePendingNotificationRequests(withIdentifiers identifiers: [String]) {
requests.removeAll { req -> Bool in
identifiers.contains(req.identifier)
Expand Down

0 comments on commit 6f52f16

Please sign in to comment.