blob: 714ddd47f1e05904b9ecbfd228f07ede6cc02747 [file] [log] [blame]
Alexandre Lision8521baa2015-03-13 11:08:00 -04001/*
Alexandre Lision9fe374b2016-01-06 10:17:31 -05002 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
Alexandre Lision8521baa2015-03-13 11:08:00 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Alexandre Lision8521baa2015-03-13 11:08:00 -040018 */
Alexandre Lisionb9f3f942016-07-23 14:29:33 -040019#import <SystemConfiguration/SystemConfiguration.h>
20
Alexandre Lision5855b6a2015-02-03 11:31:05 -050021#import "AppDelegate.h"
22
Kateryna Kostiuke3503842018-12-12 16:39:45 -050023//lrc
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040024#import <api/lrc.h>
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050025#import <api/newaccountmodel.h>
Kateryna Kostiuke3503842018-12-12 16:39:45 -050026#import <api/behaviorcontroller.h>
27#import <api/conversation.h>
28#import <api/newcallmodel.h>
Kateryna Kostiukabf4e272017-04-18 14:18:00 -040029
Alexandre Lision745e4d62015-03-22 20:03:10 -040030
Alexandre Lision3d4143a2015-06-10 14:27:49 -040031#if ENABLE_SPARKLE
32#import <Sparkle/Sparkle.h>
33#endif
34
Alexandre Lisionc65310c2015-04-23 16:44:23 -040035#import "Constants.h"
Alexandre Lision745e4d62015-03-22 20:03:10 -040036#import "RingWizardWC.h"
Alexandre Lision62005312016-01-28 15:55:16 -050037#import "DialpadWC.h"
Kateryna Kostiuke3503842018-12-12 16:39:45 -050038#import "utils.h"
Alexandre Lision745e4d62015-03-22 20:03:10 -040039
Alexandre Lision3d4143a2015-06-10 14:27:49 -040040#if ENABLE_SPARKLE
41@interface AppDelegate() <SUUpdaterDelegate>
42#else
Alexandre Lision745e4d62015-03-22 20:03:10 -040043@interface AppDelegate()
Alexandre Lision3d4143a2015-06-10 14:27:49 -040044#endif
Alexandre Lision745e4d62015-03-22 20:03:10 -040045
46@property RingWindowController* ringWindowController;
47@property RingWizardWC* wizard;
Alexandre Lision62005312016-01-28 15:55:16 -050048@property DialpadWC* dialpad;
Alexandre Lisionb9f3f942016-07-23 14:29:33 -040049@property (nonatomic, strong) dispatch_queue_t scNetworkQueue;
50@property (nonatomic, assign) SCNetworkReachabilityRef currentReachability;
Adrien Béraud022b57a2018-09-15 15:49:07 -040051@property (strong) id activity;
Alexandre Lision745e4d62015-03-22 20:03:10 -040052
53@end
54
Kateryna Kostiuke3503842018-12-12 16:39:45 -050055NSString * const MESSAGE_NOTIFICATION = @"message_notification_type";
56NSString * const CALL_NOTIFICATION = @"call_notification_type";
57NSString * const CONTACT_REQUEST_NOTIFICATION = @"contact_request_notification_type";
58
59NSString * const ACCOUNT_ID = @"account_id_notification_info";
60NSString * const CALL_ID = @"call_id_notification_info";
61NSString * const CONVERSATION_ID = @"conversation_id_notification_info";
62NSString * const CONTACT_URI = @"contact_uri_notification_info";
63NSString * const NOTIFICATION_TYPE = @"contact_type_notification_info";
64
65
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040066@implementation AppDelegate {
Alexandre Lision5855b6a2015-02-03 11:31:05 -050067
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040068std::unique_ptr<lrc::api::Lrc> lrc;
69}
Andreas Traczyke4d6e782018-03-22 17:51:30 -040070
Alexandre Lision5855b6a2015-02-03 11:31:05 -050071- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Kateryna Kostiuk0bc4c592018-06-05 13:35:19 -040072
73 // hide "Check for update" menu item when sparkle is disabled
74 NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
75 NSMenu *ringMenu = [[mainMenu itemAtIndex:0] submenu];
76 NSMenuItem *updateItem = [ringMenu itemAtIndex:1];
77#if ENABLE_SPARKLE
78 updateItem.hidden = false;
79#else
80 updateItem.hidden = true;
81#endif
82
Kateryna Kostiuk353ca3f2019-01-08 12:02:40 -050083#ifndef NDEBUG
Alexandre Lision4a7b95e2015-02-20 10:06:43 -050084 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
Kateryna Kostiuk353ca3f2019-01-08 12:02:40 -050085#else
86 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
87#endif
Alexandre Lision4a7b95e2015-02-20 10:06:43 -050088
Alexandre Lisione4041492015-03-20 18:20:43 -040089 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
90
Edric Milaret81315412015-05-13 15:14:56 -040091 NSAppleEventManager* appleEventManager = [NSAppleEventManager sharedAppleEventManager];
92 [appleEventManager setEventHandler:self andSelector:@selector(handleQuitEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
Kateryna Kostiuk85a334e2018-12-03 15:54:19 -050093
94 dispatch_queue_t queue = NULL;
95 queue = dispatch_queue_create("scNetworkReachability", DISPATCH_QUEUE_SERIAL);
96 [self setScNetworkQueue:queue];
97 [self beginObservingReachabilityStatus];
98 NSActivityOptions options = NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled | NSActivityBackground;
99 self.activity = [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:@"Receiving calls and messages"];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400100 lrc = std::make_unique<lrc::api::Lrc>();
Edric Milaret81315412015-05-13 15:14:56 -0400101
Alexandre Lision745e4d62015-03-22 20:03:10 -0400102 if([self checkForRingAccount]) {
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400103 [self setRingtonePath];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400104 [self showMainWindow];
105 } else {
106 [self showWizard];
107 }
Alexandre Lisione4041492015-03-20 18:20:43 -0400108 [self connect];
Alexandre Lisionb9f3f942016-07-23 14:29:33 -0400109}
110
111- (void) beginObservingReachabilityStatus
112{
113 SCNetworkReachabilityRef reachabilityRef = NULL;
114
115 void (^callbackBlock)(SCNetworkReachabilityFlags) = ^(SCNetworkReachabilityFlags flags) {
Kateryna Kostiuk9217e292019-08-13 13:22:45 -0400116 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Kateryna Kostiuk44432012018-11-28 09:39:10 -0500117 lrc->connectivityChanged();
Kateryna Kostiuk9217e292019-08-13 13:22:45 -0400118 });
Alexandre Lisionb9f3f942016-07-23 14:29:33 -0400119 };
120
121 SCNetworkReachabilityContext context = {
122 .version = 0,
123 .info = (void *)CFBridgingRetain(callbackBlock),
124 .release = CFRelease
125 };
126
127 reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "test");
128 if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)){
129 if (!SCNetworkReachabilitySetDispatchQueue(reachabilityRef, [self scNetworkQueue]) ){
130 // Remove our callback if we can't use the queue
131 SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL);
132 }
133 [self setCurrentReachability:reachabilityRef];
134 }
135}
136
137- (void) endObsvervingReachabilityStatusForHost:(NSString *)__unused host
138{
139 // Un-set the dispatch queue
140 if (SCNetworkReachabilitySetDispatchQueue([self currentReachability], NULL) ){
141 SCNetworkReachabilitySetCallback([self currentReachability], NULL, NULL);
142 }
143}
144
145static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkConnectionFlags flags, void* info)
146{
147 void (^callbackBlock)(SCNetworkReachabilityFlags) = (__bridge id)info;
148 callbackBlock(flags);
Alexandre Lisione4041492015-03-20 18:20:43 -0400149}
150
151- (void) connect
152{
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500153 QObject::connect(&lrc->getBehaviorController(),
154 &lrc::api::BehaviorController::newTrustRequest,
155 [self] (const std::string& accountId, const std::string& contactUri) {
156 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ContactRequestNotifications];
157 if(!shouldNotify) {
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500158 return;
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500159 }
160 NSUserNotification* notification = [[NSUserNotification alloc] init];
161 auto contactModel = lrc->getAccountModel()
162 .getAccountInfo(accountId).contactModel.get();
163 NSString* name = contactModel->getContact(contactUri)
164 .registeredName.empty() ?
165 @(contactUri.c_str()) :
166 @(contactModel->getContact(contactUri).registeredName.c_str());
167 NSString* localizedMessage =
168 NSLocalizedString(@"Send you a contact request",
169 @"Notification message");
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500170
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500171 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
172 userInfo[ACCOUNT_ID] = @(accountId.c_str());
173 userInfo[CONTACT_URI] = @(contactUri.c_str());
174 userInfo[NOTIFICATION_TYPE] = CONTACT_REQUEST_NOTIFICATION;
175
176 [notification setTitle: name];
177 notification.informativeText = localizedMessage;
178 [notification setSoundName:NSUserNotificationDefaultSoundName];
179 [notification setUserInfo: userInfo];
180
181 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
182
183 });
184
185 QObject::connect(&lrc->getBehaviorController(),
186 &lrc::api::BehaviorController::showIncomingCallView,
187 [self] (const std::string& accountId, lrc::api::conversation::Info conversationInfo) {
188 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::CallNotifications];
189 if(!shouldNotify) {
190 return;
191 }
Kateryna Kostiuk383bcfd2019-01-04 16:59:38 -0500192 bool isIncoming = false;
193 auto callModel = lrc->getAccountModel()
194 .getAccountInfo(accountId).callModel.get();
195 if(callModel->hasCall(conversationInfo.callId)) {
196 isIncoming = !callModel->getCall(conversationInfo.callId).isOutgoing;
197 }
198 if(!isIncoming) {
199 return;
200 }
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500201 NSString* name = bestIDForConversation(conversationInfo, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500202 NSUserNotification* notification = [[NSUserNotification alloc] init];
203
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500204 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
205 userInfo[ACCOUNT_ID] = @(accountId.c_str());
206 userInfo[CALL_ID] = @(conversationInfo.callId.c_str());
207 userInfo[CONVERSATION_ID] = @(conversationInfo.uid.c_str());
208 userInfo[NOTIFICATION_TYPE] = CALL_NOTIFICATION;
209
210 NSString* localizedTitle = [NSString stringWithFormat:
211 NSLocalizedString(@"Incoming call from %@", @"Incoming call from {Name}"),
212 name];
213 // try to activate action button
214 @try {
215 [notification setValue:@YES forKey:@"_showsButtons"];
216 }
217 @catch (NSException *exception) {
218 NSLog(@"Action button not activable on notification");
219 }
220 [notification setUserInfo: userInfo];
221 [notification setOtherButtonTitle:NSLocalizedString(@"Refuse", @"Button Action")];
222 [notification setActionButtonTitle:NSLocalizedString(@"Accept", @"Button Action")];
223 [notification setTitle:localizedTitle];
224 [notification setSoundName:NSUserNotificationDefaultSoundName];
225
226 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
227 });
228
229 QObject::connect(&lrc->getBehaviorController(),
230 &lrc::api::BehaviorController::newUnreadInteraction,
231 [self] (const std::string& accountId, const std::string& conversation,
232 uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
233 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::MessagesNotifications];
234 if(!shouldNotify) {
235 return;
236 }
237 NSUserNotification* notification = [[NSUserNotification alloc] init];
238
239 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
240 userInfo[ACCOUNT_ID] = @(accountId.c_str());
241 userInfo[CONVERSATION_ID] = @(conversation.c_str());
242 userInfo[NOTIFICATION_TYPE] = MESSAGE_NOTIFICATION;
243 NSString* name = @(interaction.authorUri.c_str());
244 auto convIt = getConversationFromUid(conversation, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
245 auto convQueue = lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get()->allFilteredConversations();
246 if (convIt != convQueue.end()) {
247 name = bestIDForConversation(*convIt, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
248 }
249 NSString* localizedTitle = [NSString stringWithFormat:
250 NSLocalizedString(@"Incoming message from %@",@"Incoming message from {Name}"),
251 name];
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500252
253 [notification setTitle:localizedTitle];
254 [notification setSoundName:NSUserNotificationDefaultSoundName];
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500255 [notification setSubtitle:@(interaction.body.c_str())];
256 [notification setUserInfo: userInfo];
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500257
258 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
259 });
Alexandre Lisione4041492015-03-20 18:20:43 -0400260}
261
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500262- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDismissAlert:(NSUserNotification *)alert {
263 // check if user click refuse on incoming call notifications
264 if(alert.activationType != NSUserNotificationActivationTypeNone) {
265 return;
Alexandre Lision34607032016-02-08 16:16:49 -0500266 }
Alexandre Lision34607032016-02-08 16:16:49 -0500267
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500268 auto info = alert.userInfo;
269 if(!info) {
270 return;
271 }
272 NSString* identifier = info[NOTIFICATION_TYPE];
273 NSString* callId = info[CALL_ID];
274 NSString* accountId = info[ACCOUNT_ID];
275 if(!identifier || !callId || !accountId) {
276 return;
277 }
278 if([identifier isEqualToString: CALL_NOTIFICATION]) {
279 auto accountInfo = &lrc->getAccountModel().getAccountInfo([accountId UTF8String]);
280 if (accountInfo == nil)
281 return;
282 auto* callModel = accountInfo->callModel.get();
283 callModel->hangUp([callId UTF8String]);
284 }
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500285}
286
Alexandre Lision34607032016-02-08 16:16:49 -0500287- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
288{
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500289 auto info = notification.userInfo;
290 if(!info) {
291 return;
292 }
293 NSString* identifier = info[NOTIFICATION_TYPE];
294 if([identifier isEqualToString: CALL_NOTIFICATION]) {
295 if(notification.activationType == NSUserNotificationActivationTypeActionButtonClicked
296 || notification.activationType == NSUserNotificationActivationTypeContentsClicked) {
297 NSString* callId = info[CALL_ID];
298 NSString* accountId = info[ACCOUNT_ID];
299 NSString *conversationId = info[CONVERSATION_ID];
300 auto accountInfo = &lrc->getAccountModel().getAccountInfo([accountId UTF8String]);
301 if (accountInfo == nil)
302 return;
303 auto* callModel = accountInfo->callModel.get();
304 callModel->accept([callId UTF8String]);
Alexandre Lision34607032016-02-08 16:16:49 -0500305 [self.ringWindowController.window deminiaturize:self];
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500306 [_ringWindowController showCall:callId forAccount:accountId forConversation:conversationId];
307 }
308 } else if(notification.activationType == NSUserNotificationActivationTypeContentsClicked) {
309 [self.ringWindowController.window deminiaturize:self];
310 if([identifier isEqualToString: MESSAGE_NOTIFICATION]) {
311 NSString* accountId = info[ACCOUNT_ID];
312 NSString *conversationId = info[CONVERSATION_ID];
313 [_ringWindowController showConversation:conversationId forAccount:accountId];
314 } else if([identifier isEqualToString: CONTACT_REQUEST_NOTIFICATION]) {
315 NSString* accountId = info[ACCOUNT_ID];
316 NSString *contactUri = info[CONTACT_URI];
317 [_ringWindowController showContactRequestFor:accountId contactUri: contactUri];
Alexandre Lision34607032016-02-08 16:16:49 -0500318 }
319 }
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500320 [[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications];
Alexandre Lision34607032016-02-08 16:16:49 -0500321}
322
Alexandre Lision745e4d62015-03-22 20:03:10 -0400323- (void) showWizard
324{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400325 if(self.wizard == nil) {
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400326 self.wizard = [[RingWizardWC alloc] initWithNibName:@"RingWizard" bundle: nil accountmodel: &lrc->getAccountModel()];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400327 }
Alexandre Lision76d59692016-01-20 18:06:05 -0500328 [self.wizard.window makeKeyAndOrderFront:self];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400329}
330
331- (void) showMainWindow
332{
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400333 if(self.ringWindowController == nil) {
Kateryna Kostiukf6317422018-09-27 17:08:20 -0400334 self.ringWindowController = [[RingWindowController alloc] initWithWindowNibName:@"RingWindow" bundle: nil accountModel:&lrc->getAccountModel() dataTransferModel:&lrc->getDataTransferModel() behaviourController:&lrc->getBehaviorController() avModel: &lrc->getAVModel()];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400335 }
Kateryna Kostiuk465cfbe2018-06-05 16:13:05 -0400336 [[NSApplication sharedApplication] removeWindowsItem:self.wizard.window];
Kateryna Kostiukb0db48e2019-01-10 16:03:55 -0500337 self.wizard = nil;
Alexandre Lision745e4d62015-03-22 20:03:10 -0400338 [self.ringWindowController.window makeKeyAndOrderFront:self];
339}
340
Alexandre Lision62005312016-01-28 15:55:16 -0500341- (void) showDialpad
342{
343 if (self.dialpad == nil) {
344 self.dialpad = [[DialpadWC alloc] initWithWindowNibName:@"Dialpad"];
345 }
346 [self.dialpad.window makeKeyAndOrderFront:self];
347}
348
Kateryna Kostiuk5d90c3b2019-07-18 12:03:52 -0400349-(std::vector<std::string>) getActiveCalls {
350 return lrc->activeCalls();
351}
Alexandre Lision62005312016-01-28 15:55:16 -0500352
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400353-(void)setRingtonePath {
354 std::vector<std::string> accounts = lrc->getAccountModel().getAccountList();
355 NSFileManager *fileManager = [NSFileManager defaultManager];
356 for (auto account: accounts) {
357 lrc::api::account::ConfProperties_t accountProperties = lrc->getAccountModel().getAccountConfig(account);
358 NSString *ringtonePath = @(accountProperties.Ringtone.ringtonePath.c_str());
359 if (![fileManager fileExistsAtPath: ringtonePath]) {
360 accountProperties.Ringtone.ringtonePath = [defaultRingtonePath() UTF8String];
361 lrc->getAccountModel().setAccountConfig(account, accountProperties);
362 }
363 }
364}
365
Alexandre Lision745e4d62015-03-22 20:03:10 -0400366- (BOOL) checkForRingAccount
367{
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500368 return !lrc->getAccountModel().getAccountList().empty();
Alexandre Lision745e4d62015-03-22 20:03:10 -0400369}
370
Alexandre Lision18e1fcd2015-08-04 14:38:42 -0400371-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
372{
373 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
374 [appleEventManager setEventHandler:self
375 andSelector:@selector(handleGetURLEvent:withReplyEvent:)
376 forEventClass:kInternetEventClass andEventID:kAEGetURL];
377}
378
Alexandre Lision745e4d62015-03-22 20:03:10 -0400379- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
380{
381 if([self checkForRingAccount]) {
382 [self showMainWindow];
383 } else {
384 [self showWizard];
385 }
386 return YES;
387}
388
Edric Milaret81315412015-05-13 15:14:56 -0400389- (void)handleQuitEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
390{
Kateryna Kostiuk0c0344a2018-07-27 10:35:01 -0400391 [[NSApplication sharedApplication] terminate:self];
Edric Milaret81315412015-05-13 15:14:56 -0400392}
393
394-(void)applicationWillTerminate:(NSNotification *)notification
395{
Alexandre Lision76d59692016-01-20 18:06:05 -0500396 [self cleanExit];
397}
398
399- (void) cleanExit
400{
Adrien Béraud022b57a2018-09-15 15:49:07 -0400401 if (self.activity != nil) {
402 [[NSProcessInfo processInfo] endActivity:self.activity];
403 self.activity = nil;
Andreas Traczyke4d6e782018-03-22 17:51:30 -0400404 }
Alexandre Lision76d59692016-01-20 18:06:05 -0500405 [self.wizard close];
406 [self.ringWindowController close];
Kateryna Kostiuk26526f22019-08-13 13:20:21 -0400407 lrc.reset();
Edric Milaret81315412015-05-13 15:14:56 -0400408}
409
Alexandre Lision3d4143a2015-06-10 14:27:49 -0400410#if ENABLE_SPARKLE
411
Alexandre Lision76d59692016-01-20 18:06:05 -0500412#pragma mark - Sparkle delegate
Alexandre Lision3d4143a2015-06-10 14:27:49 -0400413
414- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update
415{
416 [NSApp activateIgnoringOtherApps:YES];
417}
418
419- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle
420{
421 return YES;
422}
423
424- (BOOL)updaterShouldRelaunchApplication:(SUUpdater *)updater
425{
426 return YES;
427}
428
429- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error
430{
431 NSLog(@"Error:%@", error.localizedDescription);
432}
433
434#endif
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500435@end