blob: fb015a5a1df065d03d11f895b905f75b2a8a8cd9 [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
Alexandre Lisione4041492015-03-20 18:20:43 -040024#import <callmodel.h>
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040025#import <api/lrc.h>
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050026#import <api/newaccountmodel.h>
Kateryna Kostiuke3503842018-12-12 16:39:45 -050027#import <api/behaviorcontroller.h>
28#import <api/conversation.h>
29#import <api/newcallmodel.h>
Kateryna Kostiukabf4e272017-04-18 14:18:00 -040030
Alexandre Lision745e4d62015-03-22 20:03:10 -040031
Alexandre Lision3d4143a2015-06-10 14:27:49 -040032#if ENABLE_SPARKLE
33#import <Sparkle/Sparkle.h>
34#endif
35
Alexandre Lisionc65310c2015-04-23 16:44:23 -040036#import "Constants.h"
Alexandre Lision745e4d62015-03-22 20:03:10 -040037#import "RingWizardWC.h"
Alexandre Lision62005312016-01-28 15:55:16 -050038#import "DialpadWC.h"
Kateryna Kostiuke3503842018-12-12 16:39:45 -050039#import "utils.h"
Alexandre Lision745e4d62015-03-22 20:03:10 -040040
Alexandre Lision3d4143a2015-06-10 14:27:49 -040041#if ENABLE_SPARKLE
42@interface AppDelegate() <SUUpdaterDelegate>
43#else
Alexandre Lision745e4d62015-03-22 20:03:10 -040044@interface AppDelegate()
Alexandre Lision3d4143a2015-06-10 14:27:49 -040045#endif
Alexandre Lision745e4d62015-03-22 20:03:10 -040046
47@property RingWindowController* ringWindowController;
48@property RingWizardWC* wizard;
Alexandre Lision62005312016-01-28 15:55:16 -050049@property DialpadWC* dialpad;
Alexandre Lisionb9f3f942016-07-23 14:29:33 -040050@property (nonatomic, strong) dispatch_queue_t scNetworkQueue;
51@property (nonatomic, assign) SCNetworkReachabilityRef currentReachability;
Adrien Béraud022b57a2018-09-15 15:49:07 -040052@property (strong) id activity;
Alexandre Lision745e4d62015-03-22 20:03:10 -040053
54@end
55
Kateryna Kostiuke3503842018-12-12 16:39:45 -050056NSString * const MESSAGE_NOTIFICATION = @"message_notification_type";
57NSString * const CALL_NOTIFICATION = @"call_notification_type";
58NSString * const CONTACT_REQUEST_NOTIFICATION = @"contact_request_notification_type";
59
60NSString * const ACCOUNT_ID = @"account_id_notification_info";
61NSString * const CALL_ID = @"call_id_notification_info";
62NSString * const CONVERSATION_ID = @"conversation_id_notification_info";
63NSString * const CONTACT_URI = @"contact_uri_notification_info";
64NSString * const NOTIFICATION_TYPE = @"contact_type_notification_info";
65
66
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040067@implementation AppDelegate {
Alexandre Lision5855b6a2015-02-03 11:31:05 -050068
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040069std::unique_ptr<lrc::api::Lrc> lrc;
70}
Andreas Traczyke4d6e782018-03-22 17:51:30 -040071
Alexandre Lision5855b6a2015-02-03 11:31:05 -050072- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Kateryna Kostiuk0bc4c592018-06-05 13:35:19 -040073
74 // hide "Check for update" menu item when sparkle is disabled
75 NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
76 NSMenu *ringMenu = [[mainMenu itemAtIndex:0] submenu];
77 NSMenuItem *updateItem = [ringMenu itemAtIndex:1];
78#if ENABLE_SPARKLE
79 updateItem.hidden = false;
80#else
81 updateItem.hidden = true;
82#endif
83
Kateryna Kostiuk353ca3f2019-01-08 12:02:40 -050084#ifndef NDEBUG
Alexandre Lision4a7b95e2015-02-20 10:06:43 -050085 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
Kateryna Kostiuk353ca3f2019-01-08 12:02:40 -050086#else
87 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
88#endif
89// [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
90// [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSConstraintBasedLayoutLogUnsatisfiable"];
91// [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"__NSConstraintBasedLayoutLogUnsatisfiable"];
Alexandre Lision4a7b95e2015-02-20 10:06:43 -050092
Alexandre Lisione4041492015-03-20 18:20:43 -040093 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
94
Edric Milaret81315412015-05-13 15:14:56 -040095 NSAppleEventManager* appleEventManager = [NSAppleEventManager sharedAppleEventManager];
96 [appleEventManager setEventHandler:self andSelector:@selector(handleQuitEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
Kateryna Kostiuk85a334e2018-12-03 15:54:19 -050097
98 dispatch_queue_t queue = NULL;
99 queue = dispatch_queue_create("scNetworkReachability", DISPATCH_QUEUE_SERIAL);
100 [self setScNetworkQueue:queue];
101 [self beginObservingReachabilityStatus];
102 NSActivityOptions options = NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled | NSActivityBackground;
103 self.activity = [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:@"Receiving calls and messages"];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400104 lrc = std::make_unique<lrc::api::Lrc>();
Edric Milaret81315412015-05-13 15:14:56 -0400105
Alexandre Lision745e4d62015-03-22 20:03:10 -0400106 if([self checkForRingAccount]) {
107 [self showMainWindow];
108 } else {
109 [self showWizard];
110 }
Alexandre Lisione4041492015-03-20 18:20:43 -0400111 [self connect];
Alexandre Lisionb9f3f942016-07-23 14:29:33 -0400112}
113
114- (void) beginObservingReachabilityStatus
115{
116 SCNetworkReachabilityRef reachabilityRef = NULL;
117
118 void (^callbackBlock)(SCNetworkReachabilityFlags) = ^(SCNetworkReachabilityFlags flags) {
119 BOOL reachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
120 [[NSOperationQueue mainQueue] addOperationWithBlock:^{
Kateryna Kostiuk44432012018-11-28 09:39:10 -0500121 lrc->connectivityChanged();
Alexandre Lisionb9f3f942016-07-23 14:29:33 -0400122 }];
123 };
124
125 SCNetworkReachabilityContext context = {
126 .version = 0,
127 .info = (void *)CFBridgingRetain(callbackBlock),
128 .release = CFRelease
129 };
130
131 reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "test");
132 if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)){
133 if (!SCNetworkReachabilitySetDispatchQueue(reachabilityRef, [self scNetworkQueue]) ){
134 // Remove our callback if we can't use the queue
135 SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL);
136 }
137 [self setCurrentReachability:reachabilityRef];
138 }
139}
140
141- (void) endObsvervingReachabilityStatusForHost:(NSString *)__unused host
142{
143 // Un-set the dispatch queue
144 if (SCNetworkReachabilitySetDispatchQueue([self currentReachability], NULL) ){
145 SCNetworkReachabilitySetCallback([self currentReachability], NULL, NULL);
146 }
147}
148
149static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkConnectionFlags flags, void* info)
150{
151 void (^callbackBlock)(SCNetworkReachabilityFlags) = (__bridge id)info;
152 callbackBlock(flags);
Alexandre Lisione4041492015-03-20 18:20:43 -0400153}
154
155- (void) connect
156{
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500157 QObject::connect(&lrc->getBehaviorController(),
158 &lrc::api::BehaviorController::newTrustRequest,
159 [self] (const std::string& accountId, const std::string& contactUri) {
160 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ContactRequestNotifications];
161 if(!shouldNotify) {
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500162 return;
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500163 }
164 NSUserNotification* notification = [[NSUserNotification alloc] init];
165 auto contactModel = lrc->getAccountModel()
166 .getAccountInfo(accountId).contactModel.get();
167 NSString* name = contactModel->getContact(contactUri)
168 .registeredName.empty() ?
169 @(contactUri.c_str()) :
170 @(contactModel->getContact(contactUri).registeredName.c_str());
171 NSString* localizedMessage =
172 NSLocalizedString(@"Send you a contact request",
173 @"Notification message");
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500174
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500175 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
176 userInfo[ACCOUNT_ID] = @(accountId.c_str());
177 userInfo[CONTACT_URI] = @(contactUri.c_str());
178 userInfo[NOTIFICATION_TYPE] = CONTACT_REQUEST_NOTIFICATION;
179
180 [notification setTitle: name];
181 notification.informativeText = localizedMessage;
182 [notification setSoundName:NSUserNotificationDefaultSoundName];
183 [notification setUserInfo: userInfo];
184
185 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
186
187 });
188
189 QObject::connect(&lrc->getBehaviorController(),
190 &lrc::api::BehaviorController::showIncomingCallView,
191 [self] (const std::string& accountId, lrc::api::conversation::Info conversationInfo) {
192 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::CallNotifications];
193 if(!shouldNotify) {
194 return;
195 }
Kateryna Kostiuk383bcfd2019-01-04 16:59:38 -0500196 bool isIncoming = false;
197 auto callModel = lrc->getAccountModel()
198 .getAccountInfo(accountId).callModel.get();
199 if(callModel->hasCall(conversationInfo.callId)) {
200 isIncoming = !callModel->getCall(conversationInfo.callId).isOutgoing;
201 }
202 if(!isIncoming) {
203 return;
204 }
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500205 NSString* name = bestIDForConversation(conversationInfo, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500206 NSUserNotification* notification = [[NSUserNotification alloc] init];
207
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500208 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
209 userInfo[ACCOUNT_ID] = @(accountId.c_str());
210 userInfo[CALL_ID] = @(conversationInfo.callId.c_str());
211 userInfo[CONVERSATION_ID] = @(conversationInfo.uid.c_str());
212 userInfo[NOTIFICATION_TYPE] = CALL_NOTIFICATION;
213
214 NSString* localizedTitle = [NSString stringWithFormat:
215 NSLocalizedString(@"Incoming call from %@", @"Incoming call from {Name}"),
216 name];
217 // try to activate action button
218 @try {
219 [notification setValue:@YES forKey:@"_showsButtons"];
220 }
221 @catch (NSException *exception) {
222 NSLog(@"Action button not activable on notification");
223 }
224 [notification setUserInfo: userInfo];
225 [notification setOtherButtonTitle:NSLocalizedString(@"Refuse", @"Button Action")];
226 [notification setActionButtonTitle:NSLocalizedString(@"Accept", @"Button Action")];
227 [notification setTitle:localizedTitle];
228 [notification setSoundName:NSUserNotificationDefaultSoundName];
229
230 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
231 });
232
233 QObject::connect(&lrc->getBehaviorController(),
234 &lrc::api::BehaviorController::newUnreadInteraction,
235 [self] (const std::string& accountId, const std::string& conversation,
236 uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
237 BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::MessagesNotifications];
238 if(!shouldNotify) {
239 return;
240 }
241 NSUserNotification* notification = [[NSUserNotification alloc] init];
242
243 NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
244 userInfo[ACCOUNT_ID] = @(accountId.c_str());
245 userInfo[CONVERSATION_ID] = @(conversation.c_str());
246 userInfo[NOTIFICATION_TYPE] = MESSAGE_NOTIFICATION;
247 NSString* name = @(interaction.authorUri.c_str());
248 auto convIt = getConversationFromUid(conversation, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
249 auto convQueue = lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get()->allFilteredConversations();
250 if (convIt != convQueue.end()) {
251 name = bestIDForConversation(*convIt, *lrc->getAccountModel().getAccountInfo(accountId).conversationModel.get());
252 }
253 NSString* localizedTitle = [NSString stringWithFormat:
254 NSLocalizedString(@"Incoming message from %@",@"Incoming message from {Name}"),
255 name];
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500256
257 [notification setTitle:localizedTitle];
258 [notification setSoundName:NSUserNotificationDefaultSoundName];
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500259 [notification setSubtitle:@(interaction.body.c_str())];
260 [notification setUserInfo: userInfo];
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500261
262 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
263 });
Alexandre Lisione4041492015-03-20 18:20:43 -0400264}
265
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500266- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDismissAlert:(NSUserNotification *)alert {
267 // check if user click refuse on incoming call notifications
268 if(alert.activationType != NSUserNotificationActivationTypeNone) {
269 return;
Alexandre Lision34607032016-02-08 16:16:49 -0500270 }
Alexandre Lision34607032016-02-08 16:16:49 -0500271
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500272 auto info = alert.userInfo;
273 if(!info) {
274 return;
275 }
276 NSString* identifier = info[NOTIFICATION_TYPE];
277 NSString* callId = info[CALL_ID];
278 NSString* accountId = info[ACCOUNT_ID];
279 if(!identifier || !callId || !accountId) {
280 return;
281 }
282 if([identifier isEqualToString: CALL_NOTIFICATION]) {
283 auto accountInfo = &lrc->getAccountModel().getAccountInfo([accountId UTF8String]);
284 if (accountInfo == nil)
285 return;
286 auto* callModel = accountInfo->callModel.get();
287 callModel->hangUp([callId UTF8String]);
288 }
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500289}
290
Alexandre Lision34607032016-02-08 16:16:49 -0500291- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
292{
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500293 auto info = notification.userInfo;
294 if(!info) {
295 return;
296 }
297 NSString* identifier = info[NOTIFICATION_TYPE];
298 if([identifier isEqualToString: CALL_NOTIFICATION]) {
299 if(notification.activationType == NSUserNotificationActivationTypeActionButtonClicked
300 || notification.activationType == NSUserNotificationActivationTypeContentsClicked) {
301 NSString* callId = info[CALL_ID];
302 NSString* accountId = info[ACCOUNT_ID];
303 NSString *conversationId = info[CONVERSATION_ID];
304 auto accountInfo = &lrc->getAccountModel().getAccountInfo([accountId UTF8String]);
305 if (accountInfo == nil)
306 return;
307 auto* callModel = accountInfo->callModel.get();
308 callModel->accept([callId UTF8String]);
Alexandre Lision34607032016-02-08 16:16:49 -0500309 [self.ringWindowController.window deminiaturize:self];
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500310 [_ringWindowController showCall:callId forAccount:accountId forConversation:conversationId];
311 }
312 } else if(notification.activationType == NSUserNotificationActivationTypeContentsClicked) {
313 [self.ringWindowController.window deminiaturize:self];
314 if([identifier isEqualToString: MESSAGE_NOTIFICATION]) {
315 NSString* accountId = info[ACCOUNT_ID];
316 NSString *conversationId = info[CONVERSATION_ID];
317 [_ringWindowController showConversation:conversationId forAccount:accountId];
318 } else if([identifier isEqualToString: CONTACT_REQUEST_NOTIFICATION]) {
319 NSString* accountId = info[ACCOUNT_ID];
320 NSString *contactUri = info[CONTACT_URI];
321 [_ringWindowController showContactRequestFor:accountId contactUri: contactUri];
Alexandre Lision34607032016-02-08 16:16:49 -0500322 }
323 }
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500324 [[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications];
Alexandre Lision34607032016-02-08 16:16:49 -0500325}
326
Alexandre Lision745e4d62015-03-22 20:03:10 -0400327- (void) showWizard
328{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400329 if(self.wizard == nil) {
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400330 self.wizard = [[RingWizardWC alloc] initWithNibName:@"RingWizard" bundle: nil accountmodel: &lrc->getAccountModel()];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400331 }
Alexandre Lision76d59692016-01-20 18:06:05 -0500332 [self.wizard.window makeKeyAndOrderFront:self];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400333}
334
335- (void) showMainWindow
336{
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400337 if(self.ringWindowController == nil) {
Kateryna Kostiukf6317422018-09-27 17:08:20 -0400338 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 -0400339 }
Kateryna Kostiuk465cfbe2018-06-05 16:13:05 -0400340 [[NSApplication sharedApplication] removeWindowsItem:self.wizard.window];
Kateryna Kostiukb0db48e2019-01-10 16:03:55 -0500341 self.wizard = nil;
Alexandre Lision745e4d62015-03-22 20:03:10 -0400342 [self.ringWindowController.window makeKeyAndOrderFront:self];
343}
344
Alexandre Lision62005312016-01-28 15:55:16 -0500345- (void) showDialpad
346{
347 if (self.dialpad == nil) {
348 self.dialpad = [[DialpadWC alloc] initWithWindowNibName:@"Dialpad"];
349 }
350 [self.dialpad.window makeKeyAndOrderFront:self];
351}
352
353
Alexandre Lision745e4d62015-03-22 20:03:10 -0400354- (BOOL) checkForRingAccount
355{
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500356 return !lrc->getAccountModel().getAccountList().empty();
Alexandre Lision745e4d62015-03-22 20:03:10 -0400357}
358
Alexandre Lision18e1fcd2015-08-04 14:38:42 -0400359-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
360{
361 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
362 [appleEventManager setEventHandler:self
363 andSelector:@selector(handleGetURLEvent:withReplyEvent:)
364 forEventClass:kInternetEventClass andEventID:kAEGetURL];
365}
366
367/**
368 * Recognized patterns:
369 * - ring:<hash>
370 * - ring://<hash>
371 */
372- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
373{
374 NSString* query = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
375 NSURL* url = [[NSURL alloc] initWithString:query];
376 NSString* ringID = [url host];
377 if (!ringID) {
378 //not a valid NSURL, try to parse query directly
379 ringID = [query substringFromIndex:@"ring:".length];
380 }
381
382 // check for a valid ring hash
383 NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
384 BOOL valid = [[ringID stringByTrimmingCharactersInSet:hexSet] isEqualToString:@""];
385
386 if(valid && ringID.length == 40) {
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400387 Call* c = CallModel::instance().dialingCall();
Alexandre Lision18e1fcd2015-08-04 14:38:42 -0400388 c->setDialNumber(QString::fromNSString([NSString stringWithFormat:@"ring:%@",ringID]));
389 c << Call::Action::ACCEPT;
390 } else {
391 NSAlert *alert = [[NSAlert alloc] init];
392 [alert addButtonWithTitle:@"OK"];
393 [alert setMessageText:@"Error"];
394 [alert setInformativeText:@"ringID cannot be read from this URL."];
395 [alert setAlertStyle:NSWarningAlertStyle];
396 [alert runModal];
397 }
398}
399
Alexandre Lision745e4d62015-03-22 20:03:10 -0400400- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
401{
402 if([self checkForRingAccount]) {
403 [self showMainWindow];
404 } else {
405 [self showWizard];
406 }
407 return YES;
408}
409
Edric Milaret81315412015-05-13 15:14:56 -0400410- (void)handleQuitEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
411{
Kateryna Kostiuk0c0344a2018-07-27 10:35:01 -0400412 [[NSApplication sharedApplication] terminate:self];
Edric Milaret81315412015-05-13 15:14:56 -0400413}
414
415-(void)applicationWillTerminate:(NSNotification *)notification
416{
Alexandre Lision76d59692016-01-20 18:06:05 -0500417 [self cleanExit];
418}
419
420- (void) cleanExit
421{
Adrien Béraud022b57a2018-09-15 15:49:07 -0400422 if (self.activity != nil) {
423 [[NSProcessInfo processInfo] endActivity:self.activity];
424 self.activity = nil;
Andreas Traczyke4d6e782018-03-22 17:51:30 -0400425 }
Alexandre Lision76d59692016-01-20 18:06:05 -0500426 [self.wizard close];
427 [self.ringWindowController close];
Edric Milaret81315412015-05-13 15:14:56 -0400428 [[NSApplication sharedApplication] terminate:self];
429}
430
Alexandre Lision3d4143a2015-06-10 14:27:49 -0400431#if ENABLE_SPARKLE
432
Alexandre Lision76d59692016-01-20 18:06:05 -0500433#pragma mark - Sparkle delegate
Alexandre Lision3d4143a2015-06-10 14:27:49 -0400434
435- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update
436{
437 [NSApp activateIgnoringOtherApps:YES];
438}
439
440- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle
441{
442 return YES;
443}
444
445- (BOOL)updaterShouldRelaunchApplication:(SUUpdater *)updater
446{
447 return YES;
448}
449
450- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error
451{
452 NSLog(@"Error:%@", error.localizedDescription);
453}
454
455#endif
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500456@end