-
Notifications
You must be signed in to change notification settings - Fork 8
/
AppDelegate.swift
219 lines (182 loc) · 9.04 KB
/
AppDelegate.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
Infomaniak kDrive - iOS App
Copyright (C) 2021 Infomaniak Network SA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Atlantis
import AVFoundation
import BackgroundTasks
import CocoaLumberjackSwift
import InfomaniakCore
import InfomaniakCoreUIKit
import InfomaniakDI
import InfomaniakLogin
import kDriveCore
import kDriveResources
import Kingfisher
import os.log
import StoreKit
import UIKit
import UserNotifications
import VersionChecker
@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
/// Making sure the DI is registered at a very early stage of the app launch.
private let dependencyInjectionHook = EarlyDIHook(context: .app)
private var reachabilityListener: ReachabilityListener!
@LazyInjectService var infomaniakLogin: InfomaniakLogin
@LazyInjectService var notificationHelper: NotificationsHelpable
@LazyInjectService var accountManager: AccountManageable
@LazyInjectService var backgroundTasksService: BackgroundTasksServiceable
@LazyInjectService var appRestorationService: AppRestorationServiceable
@LazyInjectService var appNavigable: AppNavigable
@LazyInjectService var backgroundDownloadSessionManager: BackgroundDownloadSessionManager
@LazyInjectService var backgroundUploadSessionManager: BackgroundUploadSessionManager
// MARK: - UIApplicationDelegate
func application(_ application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
Logging.initLogging()
Log.appDelegate("Application starting in foreground ? \(UIApplication.shared.applicationState != .background)")
ImageCache.default.memoryStorage.config.totalCostLimit = Constants.ImageCache.memorySizeLimit
// Must define a limit, unlimited otherwise
ImageCache.default.diskStorage.config.sizeLimit = Constants.ImageCache.diskSizeLimit
reachabilityListener = ReachabilityListener.instance
ApiEnvironment.current = .prod
// Start audio session
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch {
Log.appDelegate("Error while setting playback audio category", level: .error)
SentryDebug.capture(error: error)
}
backgroundTasksService.registerBackgroundTasks()
// In some cases the application can show the old Nextcloud import notification badge
UIApplication.shared.applicationIconBadgeNumber = 0
notificationHelper.askForPermissions()
notificationHelper.registerCategories()
UNUserNotificationCenter.current().delegate = self
if CommandLine.arguments.contains("testing") {
UIView.setAnimationsEnabled(false)
}
// Attach an observer to the payment queue.
SKPaymentQueue.default().add(StoreObserver.shared)
return true
}
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Log.appDelegate("application didFinishLaunchingWithOptions")
// Register for remote notifications. This shows a permission dialog on first run, to
// show the dialog at a more appropriate time move this registration accordingly.
// [START register_for_notifications]
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in
// META: keep SonarCloud happy
}
application.registerForRemoteNotifications()
return true
}
func applicationWillTerminate(_ application: UIApplication) {
Log.appDelegate("applicationWillTerminate")
// Remove the observer.
SKPaymentQueue.default().remove(StoreObserver.shared)
// Gracefully suspend upload/download queue before exiting.
// Running operations will go on, but at least no more operations will start
DownloadQueue.instance.suspendAllOperations()
DownloadQueue.instance.cancelAllOperations()
@InjectService var uploadQueue: UploadQueueable
uploadQueue.suspendAllOperations()
uploadQueue.rescheduleRunningOperations()
// Await on upload queue to terminate gracefully, if time allows for it.
let group = TolerantDispatchGroup()
uploadQueue.waitForCompletion {
// Clean temp files once the upload queue is stoped if needed
@LazyInjectService var freeSpaceService: FreeSpaceService
freeSpaceService.auditCache()
group.leave()
}
// The documentation specifies `approximately five seconds [to] return` from applicationWillTerminate
// Therefore to not display a crash feedback on TestFlight, we give up after 4.5 seconds
DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + AppDelegateConstants.closeApplicationGiveUpTime) {
group.leave()
}
group.enter()
group.wait()
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
Log.appDelegate("Unable to register for remote notifications: \(error.localizedDescription)", level: .error)
}
func application(_ application: UIApplication,
open url: URL,
sourceApplication: String?,
annotation: Any) -> Bool {
Log.appDelegate("application open url:\(url)) sourceApplication:\(sourceApplication)")
return infomaniakLogin.handleRedirectUri(url: url)
}
}
// MARK: - User notification center delegate
extension AppDelegate: UNUserNotificationCenterDelegate {
// In Foreground
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
_ = notification.request.content.userInfo
completionHandler([.alert, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
switch response.notification.request.trigger {
case is UNPushNotificationTrigger:
processPushNotification(response.notification)
default:
if response.notification.request.content.categoryIdentifier == NotificationsHelper.CategoryIdentifier.upload {
// Upload notification
let parentId = userInfo[NotificationsHelper.UserInfoKey.parentId] as? Int
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier:
// Notification tapped: open parent folder
if let parentId,
let driveFileManager = accountManager.currentDriveFileManager,
let folder = driveFileManager.getCachedFile(id: parentId) {
appNavigable.present(file: folder, driveFileManager: driveFileManager)
}
default:
break
}
} else if response.notification.request.content.categoryIdentifier == NotificationsHelper.CategoryIdentifier
.photoSyncError {
// Show photo sync settings
appNavigable.showPhotoSyncSettings()
} else {
// Handle other notification types...
}
}
completionHandler()
}
private func processPushNotification(_ notification: UNNotification) {
UIApplication.shared.applicationIconBadgeNumber = 0
// PROCESS NOTIFICATION
// let userInfo = notification.request.content.userInfo
//
// let parentId = Int(userInfo["parentId"] as? String ?? "")
// if let parentId = parentId,
// let driveFileManager = accountManager.currentDriveFileManager,
// let folder = driveFileManager.getCachedFile(id: parentId) {
// present(file: folder, driveFileManager: driveFileManager)
// }
//
// Messaging.messaging().appDidReceiveMessage(userInfo)
}
}