Newer
Older
import CloudFilesDrive
import CloudFilesICloud
public class AppDelegate: UIResponder, UIApplicationDelegate {
@Dependency private var pushRouter: PushRouter
@Dependency private var pushHandler: PushHandling
@Dependency private var crashReporter: CrashReporter
@KeyObject(.hideAppList, defaultValue: false) var hideAppList: Bool
@KeyObject(.recordingLogs, defaultValue: true) var recordingLogs: Bool
@KeyObject(.crashReporting, defaultValue: true) var isCrashReportingEnabled: Bool
var calledStopNetwork = false
var forceFailedPendingMessages = false
var coverView: UIView?
var backgroundTimer: Timer?
public var window: UIWindow?
public func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
#if DEBUG
DependencyRegistrator.registerForMock()
#else
DependencyRegistrator.registerForLive()
#endif
if recordingLogs {
XXLogger.start()
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
crashReporter.configure()
crashReporter.setEnabled(isCrashReportingEnabled)
UNUserNotificationCenter.current().delegate = self
let window = Window()
let navController = UINavigationController(rootViewController: LaunchController())
window.rootViewController = StatusBarViewController(ToastViewController(navController))
window.backgroundColor = UIColor.white
window.makeKeyAndVisible()
self.window = window
DependencyInjection.Container.shared.register(
PushRouter.live(navigationController: navController)
)
return true
}
public func application(application: UIApplication, shouldAllowExtensionPointIdentifier: String) -> Bool {
false
}
public func applicationDidEnterBackground(_ application: UIApplication) {
if let messenger = try? DependencyInjection.Container.shared.resolve() as Messenger,
let database = try? DependencyInjection.Container.shared.resolve() as Database,
let cMix = try? messenger.cMix.tryGet() {
let backgroundTask = application.beginBackgroundTask(withName: "xx.stop.network") {}
backgroundTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
print(">>> .backgroundTimeRemaining: \(UIApplication.shared.backgroundTimeRemaining)")
guard UIApplication.shared.backgroundTimeRemaining > 8 else {
if !self.calledStopNetwork {
self.calledStopNetwork = true
try! messenger.stop()
print(">>> Called stopNetworkFollower")
} else {
if cMix.hasRunningProcesses() == false {
application.endBackgroundTask(backgroundTask)
timer.invalidate()
}
}
return
guard UIApplication.shared.backgroundTimeRemaining > 9 else {
if !self.forceFailedPendingMessages {
self.forceFailedPendingMessages = true
let query = Message.Query(status: [.sending])
let assignment = Message.Assignments(status: .sendingFailed)
_ = try? database.bulkUpdateMessages(query, assignment)
}
}
public func applicationWillResignActive(_ application: UIApplication) {
if hideAppList {
coverView?.removeFromSuperview()
coverView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
coverView?.frame = window?.bounds ?? .zero
window?.addSubview(coverView!)
public func applicationWillTerminate(_ application: UIApplication) {
if let messenger = try? DependencyInjection.Container.shared.resolve() as Messenger {
try? messenger.stop()
public func applicationWillEnterForeground(_ application: UIApplication) {
if backgroundTimer != nil {
backgroundTimer?.invalidate()
backgroundTimer = nil
print(">>> Invalidated background timer")
}
if let messenger = try? DependencyInjection.Container.shared.resolve() as Messenger,
let cMix = messenger.cMix.get() {
guard self.calledStopNetwork == true else { return }
try? cMix.startNetworkFollower(timeoutMS: 10_000)
print(">>> Called startNetworkFollower")
self.calledStopNetwork = false
}
public func applicationDidBecomeActive(_ application: UIApplication) {
application.applicationIconBadgeNumber = 0
coverView?.removeFromSuperview()
}
public func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
}
public func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let username = getUsernameFromInvitationDeepLink(incomingURL),
let router = try? DependencyInjection.Container.shared.resolve() as PushRouter else {
return false
}
router.navigateTo(.search(username: username), {})
return true
}
func getUsernameFromInvitationDeepLink(_ url: URL) -> String? {
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
components.scheme == "https",
components.host == "elixxir.io",
components.path == "/connect",
let queryItem = components.queryItems?.first(where: { $0.name == "username" }),
let username = queryItem.value {
return username
}
return nil
// MARK: Notifications
extension AppDelegate: UNUserNotificationCenterDelegate {
public func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
pushHandler.handleAction(pushRouter, userInfo, completionHandler)
}
public func application(
_ application: UIApplication,
didReceiveRemoteNotification notification: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
pushHandler.handlePush(notification, completionHandler)
}
public func application(
_: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
pushHandler.registerToken(deviceToken)
}