X-Git-Url: https://code.grnet.gr/git/pithos-macos/blobdiff_plain/c2312252f51557069c2135bf6b495f069e5db79c..97c9a632d23b88952081fc38a9e2bc03eb2a7ac9:/pithos-macos/pithos_macosAppDelegate.m diff --git a/pithos-macos/pithos_macosAppDelegate.m b/pithos-macos/pithos_macosAppDelegate.m index a03fd36..95d22ae 100644 --- a/pithos-macos/pithos_macosAppDelegate.m +++ b/pithos-macos/pithos_macosAppDelegate.m @@ -42,12 +42,11 @@ #import "PithosSyncDaemon.h" #import "ASIPithosRequest.h" #import "ASIPithos.h" -#import "ASIDownloadCache.h" #import "LastCompletedSyncTransformer.h" @implementation pithos_macosAppDelegate @synthesize pithosBrowserController, pithosPreferencesController, alwaysNo, openAtLoginEnabled, openAtLogin, activated, -currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccount, activityFacilityTimeInterval; +currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccount, activityFacilityTimeInterval, checkForUpdatesNotRunning; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self @@ -59,12 +58,12 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun // and: http://cocoatutorial.grapewave.com/2010/02/creating-andor-removing-a-login-item/ loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); if (loginItems) { - LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(), (CFStringRef)NSDefaultRunLoopMode, LSSharedFileListChanged, self); - LSSharedFileListChanged(loginItems, self); + LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(), (CFStringRef)NSDefaultRunLoopMode, LSSharedFileListChanged, (__bridge void *)(self)); + LSSharedFileListChanged(loginItems, (__bridge void *)(self)); self.openAtLoginEnabled = YES; } - userDefaults = [[NSUserDefaults standardUserDefaults] retain]; + userDefaults = [NSUserDefaults standardUserDefaults]; syncTimeInterval = [userDefaults doubleForKey:@"syncTimeInterval"]; if (syncTimeInterval <= 0.0) { @@ -98,10 +97,11 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun for (PithosAccount *pithosAccount in pithosAccounts) { [pithosAccountsDictionary setObject:pithosAccount forKey:pithosAccount.name]; if (!currentPithosAccount && pithosAccount.active) - currentPithosAccount = [pithosAccount retain]; + self.currentPithosAccount = pithosAccount; } if (!currentPithosAccount) self.currentPithosAccount = [pithosAccounts objectAtIndex:0]; + self.pithosBrowserController.pithosAccountManager = currentPithosAccount; if (currentPithosAccount.active) { [self savePithosAccounts:self]; @@ -112,12 +112,17 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun [self showPithosPreferences:self]; } - syncTimer = [[NSTimer scheduledTimerWithTimeInterval:syncTimeInterval + syncTimer = [NSTimer scheduledTimerWithTimeInterval:syncTimeInterval target:self selector:@selector(sync) userInfo:nil - repeats:YES] retain]; + repeats:YES]; [syncTimer fire]; + + @synchronized(self) { + self.checkForUpdatesNotRunning = YES; + } + [self checkForUpdates]; } // Based on: http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/ @@ -125,14 +130,14 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun - (void)awakeFromNib { NSImage *sourceImage = [NSImage imageNamed:@"pithos-large.png"]; - NSImage *smallImage = [[[NSImage alloc] initWithSize:NSMakeSize(18, 18)] autorelease]; + NSImage *smallImage = [[NSImage alloc] initWithSize:NSMakeSize(18, 18)]; [smallImage lockFocus]; [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; [sourceImage setSize:NSMakeSize(18, 18)]; - [sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy]; + [sourceImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0]; [smallImage unlockFocus]; - statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; + statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength]; [statusItem setMenu:statusMenu]; [statusItem setImage:sourceImage]; [statusItem setHighlightMode:YES]; @@ -144,7 +149,7 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]]; NSString *host = [url host]; NSString *query = [url query]; - PithosAccount *pithosAccount = [pithosAccountsDictionary objectForKey:[url lastPathComponent]]; + PithosAccount *pithosAccount = [pithosAccountsDictionary objectForKey:[ASIPithosRequest decodeFromPercentEscape:[url lastPathComponent]]]; NSProcessInfo *processInfo = [NSProcessInfo processInfo]; if ([host isEqualToString:[NSString stringWithFormat:@"%d", [processInfo processIdentifier]]] && pithosAccount && query) { // user= @@ -180,7 +185,7 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } - NSLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken); + DLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken); if ([authUser length] && [authToken length]) { [pithosAccount authenticateWithServerURL:nil authUser:authUser authToken:authToken]; [self savePithosAccounts:self]; @@ -202,7 +207,7 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { [self savePithosAccounts:self]; if ([self.pithosBrowserController operationsPending]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Pending Operations"]; [alert setInformativeText:@"There are pending operations in the browser, do you want to quit and cancel them?"]; [alert addButtonWithTitle:@"OK"]; @@ -212,7 +217,7 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun return NSTerminateCancel; } if (loginItems) { - LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(), (CFStringRef)NSDefaultRunLoopMode, LSSharedFileListChanged, self); + LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(), (CFStringRef)NSDefaultRunLoopMode, LSSharedFileListChanged, (__bridge void *)(self)); CFRelease(loginItems); } return NSTerminateNow; @@ -224,13 +229,13 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun - (void)loginItemsChanged { NSURL *appURL = [[NSBundle mainBundle] bundleURL]; LSSharedFileListItemRef appItem = NULL; - NSArray *snapshot = [NSMakeCollectable(LSSharedFileListCopySnapshot(loginItems, NULL)) autorelease]; + NSArray *snapshot = (__bridge_transfer NSArray *)(LSSharedFileListCopySnapshot(loginItems, NULL)); for (id itemObject in snapshot) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)itemObject; + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; CFURLRef currentItemURL = NULL; LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL); - if (currentItemURL && CFEqual(currentItemURL, appURL)) { + if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(appURL))) { CFRelease(currentItemURL); appItem = item; break; @@ -246,7 +251,7 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun } void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { - pithos_macosAppDelegate *self = (id)context; + pithos_macosAppDelegate *self = (__bridge id)context; [self loginItemsChanged]; } @@ -273,13 +278,13 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { } else if (anOpenAtLogin != openAtLogin) { NSURL *appURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; LSSharedFileListItemRef appItem = NULL; - NSArray *snapshot = [NSMakeCollectable(LSSharedFileListCopySnapshot(loginItems, NULL)) autorelease]; + NSArray *snapshot = (__bridge_transfer NSArray *)(LSSharedFileListCopySnapshot(loginItems, NULL)); for (id itemObject in snapshot) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)itemObject; + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; CFURLRef currentItemURL = NULL; LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL); - if (currentItemURL && CFEqual(currentItemURL, appURL)) { + if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(appURL))) { CFRelease(currentItemURL); appItem = item; break; @@ -290,7 +295,7 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { if (anOpenAtLogin) { if (!appItem) - LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, (CFURLRef)appURL, NULL, NULL); + LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, (__bridge CFURLRef)appURL, NULL, NULL); openAtLogin = YES; } else { if (appItem) @@ -309,9 +314,9 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { if ([menu isEqualTo:accountsMenu]) { [menu setAutoenablesItems:NO]; for (PithosAccount *pithosAccount in pithosAccounts) { - menuItem = [[[NSMenuItem alloc] initWithTitle:pithosAccount.name + menuItem = [[NSMenuItem alloc] initWithTitle:pithosAccount.name action:@selector(menuChangePithosAccount:) - keyEquivalent:@""] autorelease]; + keyEquivalent:@""]; [menuItem setRepresentedObject:pithosAccount]; [menuItem setEnabled:pithosAccount.active]; [menuItem setState:((pithosAccount.active && [currentPithosAccount isEqualTo:pithosAccount]) ? NSOnState : NSOffState)]; @@ -323,7 +328,7 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { for (PithosAccount *pithosAccount in pithosAccounts) { menuItemTitle = [NSString stringWithFormat:@"%@: %@", pithosAccount.name, - [[[[LastCompletedSyncTransformer alloc] init] autorelease] transformedValue:pithosAccount.syncLastCompleted]]; + [[[LastCompletedSyncTransformer alloc] init] transformedValue:pithosAccount.syncLastCompleted]]; if ([pithosAccount isEqualTo:syncPithosAccount] && [pithosAccount.syncDaemon isSyncing]) menuItemTitle = [menuItemTitle stringByAppendingString:@" (syncing)"]; // menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle @@ -332,15 +337,15 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { // [menuItem setRepresentedObject:pithosAccount]; // [menuItem setEnabled:pithosAccount.active]; // [menuItem setState:((pithosAccount.active && pithosAccount.syncActive) ? NSOnState : NSOffState)]; - menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:nil keyEquivalent:@""] autorelease]; + menuItem = [[NSMenuItem alloc] initWithTitle:menuItemTitle action:nil keyEquivalent:@""]; [menuItem setEnabled:NO]; [menuItem setState:NO]; [menu addItem:menuItem]; } [menu addItem:[NSMenuItem separatorItem]]; - [menu addItem:[[[NSMenuItem alloc] initWithTitle:@"Next Sync" + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Next Sync" action:@selector(sync) - keyEquivalent:@""] autorelease]]; + keyEquivalent:@""]]; } } @@ -444,6 +449,7 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { for (PithosAccount *pithosAccount in pithosAccounts) { if (pithosAccount.active) { self.currentPithosAccount = pithosAccount; + self.pithosBrowserController.pithosAccountManager = currentPithosAccount; self.pithosBrowserController.pithos = currentPithosAccount.pithos; break; } @@ -453,12 +459,86 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { [self.pithosBrowserController.window close]; [self.pithosBrowserController resetBrowser]; self.currentPithosAccount = [pithosAccounts objectAtIndex:0]; + self.pithosBrowserController.pithosAccountManager = currentPithosAccount; } } if ([self.syncPithosAccount isEqualTo:removedPithosAccount]) self.syncPithosAccount = nil; } +- (void)checkForUpdates { + @synchronized(self) { + if (!checkForUpdatesNotRunning) + return; + self.checkForUpdatesNotRunning = NO; + } + ASIHTTPRequest *checkForUpdatesRequest = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"https://code.grnet.gr/projects/pithos-macos/repository/revisions/master/raw/pithos-macos/pithos-macos-Info.plist"]]; + checkForUpdatesRequest.delegate = self; + checkForUpdatesRequest.didFinishSelector = @selector(checkForUpdatesRequestFinished:); + checkForUpdatesRequest.didFailSelector = @selector(checkForUpdatesRequestFailed:); + checkForUpdatesRequest.timeOutSeconds = 60; + checkForUpdatesRequest.numberOfTimesToRetryOnTimeout = 10; + [checkForUpdatesRequest startAsynchronous]; +} + +#pragma mark - +#pragma mark ASIHTTPRequestDelegate + +- (void)checkForUpdatesRequestFinished:(ASIHTTPRequest *)request { + if (request.responseStatusCode == 200) { + NSError *error = nil; + NSDictionary *plistDictionary = [NSPropertyListSerialization propertyListWithData:[request.responseString dataUsingEncoding:NSUTF8StringEncoding] + options:NSPropertyListImmutable + format:NULL + error:&error]; + if (!error) { + NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; + NSString *newVersion = [plistDictionary objectForKey:@"CFBundleVersion"]; + NSURL *distributionURL = [NSURL URLWithString:[plistDictionary objectForKey:@"PithosDistributionURL"]]; + if (newVersion && currentVersion && distributionURL && ([newVersion doubleValue] > [currentVersion doubleValue])) { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Updates Available"]; + [alert setInformativeText:@"An updated version is available"]; + [alert addButtonWithTitle:@"Download"]; + [alert runModal]; + [[NSWorkspace sharedWorkspace] openURL:distributionURL]; + } else if (checkForUpdatesCalledFromMenu) { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"No Updates Available"]; + [alert setInformativeText:@"You are running the latest version"]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + checkForUpdatesCalledFromMenu = NO; + } + [NSTimer scheduledTimerWithTimeInterval:86400 + target:self + selector:@selector(checkForUpdates) + userInfo:nil + repeats:YES]; + self.checkForUpdatesNotRunning = YES; + return; + } + DLog(@"Check for update plist error: %@", error); + } +} + +- (void)checkForUpdatesRequestFailed:(ASIHTTPRequest *)request { + if (checkForUpdatesCalledFromMenu) { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Check for Updates Error"]; + [alert setInformativeText:@"Cannot check for updates now, try again later"]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + checkForUpdatesCalledFromMenu = NO; + } + [NSTimer scheduledTimerWithTimeInterval:600 + target:self + selector:@selector(checkForUpdates) + userInfo:nil + repeats:YES]; + self.checkForUpdatesNotRunning = YES; +} + #pragma mark - #pragma mark Menu Actions @@ -468,7 +548,7 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { return; if (![currentPithosAccount isEqualTo:pithosAccount] && [pithosAccounts containsObject:pithosAccount]) { if ([self.pithosBrowserController operationsPending]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Pending Operations"]; [alert setInformativeText:@"There are pending operations in the browser, do you want to change accounts and cancel them?"]; [alert addButtonWithTitle:@"OK"]; @@ -478,6 +558,7 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { return; } self.currentPithosAccount = pithosAccount; + self.pithosBrowserController.pithosAccountManager = currentPithosAccount; [self showPithosBrowser:self]; self.pithosBrowserController.pithos = currentPithosAccount.pithos; } @@ -493,4 +574,11 @@ void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) { // [self savePithosAccounts:self]; //} +- (IBAction)menuCheckForUpdates:(NSMenuItem *)sender { + @synchronized(self) { + checkForUpdatesCalledFromMenu = YES; + } + [self checkForUpdates]; +} + @end