Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deactivation Fixes #516

Merged
merged 13 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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