// pithos_macosAppDelegate.m
// pithos-macos
//
-// Copyright 2011 GRNET S.A. All rights reserved.
+// Copyright 2011-2012 GRNET S.A. All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// or implied, of GRNET S.A.
#import "pithos_macosAppDelegate.h"
+#import "PithosAccount.h"
#import "PithosBrowserController.h"
#import "PithosPreferencesController.h"
+#import "PithosSyncDaemon.h"
#import "ASIPithosRequest.h"
-#import "ASIDownloadCache.h"
+#import "ASIPithos.h"
+#import "LastCompletedSyncTransformer.h"
@implementation pithos_macosAppDelegate
-@synthesize storageURLPrefix, publicURLPrefix, loginURLPrefix, aboutURL;
+@synthesize pithosBrowserController, pithosPreferencesController, alwaysNo, openAtLoginEnabled, openAtLogin, activated,
+currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccount, activityFacilityTimeInterval, checkForUpdatesNotRunning;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- NSURL *testURL;
- storageURLPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"PithosStorageURLPrefix"];
- if (!storageURLPrefix) {
- storageURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/v1"];
- } else {
- testURL = [NSURL URLWithString:storageURLPrefix];
- if (!testURL || !testURL.scheme || !testURL.host)
- storageURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/v1"];
- }
- [storageURLPrefix retain];
+ [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
+ andSelector:@selector(handleAppleEvent:withReplyEvent:)
+ forEventClass:kInternetEventClass
+ andEventID:kAEGetURL];
- publicURLPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"PithosPublicURLPrefix"];
- if (!publicURLPrefix) {
- publicURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr"];
- } else {
- testURL = [NSURL URLWithString:publicURLPrefix];
- if (!testURL || !testURL.scheme || !testURL.host)
- publicURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr"];
+ // Based on: https://github.com/Mozketo/LaunchAtLoginController
+ // 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, (__bridge void *)(self));
+ LSSharedFileListChanged(loginItems, (__bridge void *)(self));
+ self.openAtLoginEnabled = YES;
}
- [publicURLPrefix retain];
- loginURLPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"PithosLoginURLPrefix"];
- if (!loginURLPrefix) {
- loginURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/login"];
- } else {
- testURL = [NSURL URLWithString:loginURLPrefix];
- if (!testURL || !testURL.scheme || !testURL.host)
- loginURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/login"];
+ userDefaults = [NSUserDefaults standardUserDefaults];
+
+ syncTimeInterval = [userDefaults doubleForKey:@"syncTimeInterval"];
+ if (syncTimeInterval <= 0.0) {
+ syncTimeInterval = 180.0;
+ [userDefaults setDouble:syncTimeInterval forKey:@"syncTimeInterval"];
+ [userDefaults synchronize];
+ }
+
+ activityFacilityTimeInterval = [userDefaults doubleForKey:@"activityFacilityTimeInterval"];
+ if (activityFacilityTimeInterval <= 0.0) {
+ activityFacilityTimeInterval = 0.05;
+ [userDefaults setDouble:activityFacilityTimeInterval forKey:@"activityFacilityTimeInterval"];
+ [userDefaults synchronize];
}
- [loginURLPrefix retain];
- aboutURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"PithosAboutURL"];
- if (!aboutURL) {
- aboutURL = [NSString stringWithString:@"https://pithos.dev.grnet.gr/docs"];
+ NSData *tmpData = [userDefaults objectForKey:@"pithosAccounts"];
+ NSArray *tmpArray;
+ if (tmpData && (tmpArray = [NSKeyedUnarchiver unarchiveObjectWithData:tmpData]))
+ self.pithosAccounts = [NSMutableArray arrayWithArray:tmpArray];
+ else
+ self.pithosAccounts = [NSMutableArray array];
+
+ if (![pithosAccounts count]) {
+ [pithosAccounts addObject:[PithosAccount pithosAccount]];
+ self.pithosAccounts = self.pithosAccounts;
} else {
- testURL = [NSURL URLWithString:aboutURL];
- if (!testURL || !testURL.scheme || !testURL.host)
- aboutURL = [NSString stringWithString:@"https://pithos.dev.grnet.gr/docs"];
+ self.activated = YES;
}
- [aboutURL retain];
- [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
- andSelector:@selector(handleAppleEvent:withReplyEvent:)
- forEventClass:kInternetEventClass
- andEventID:kAEGetURL];
- [self showPithosBrowser:self];
+ pithosAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[pithosAccounts count]];
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ [pithosAccountsDictionary setObject:pithosAccount forKey:pithosAccount.name];
+ if (!currentPithosAccount && pithosAccount.active)
+ self.currentPithosAccount = pithosAccount;
+ }
+ if (!currentPithosAccount)
+ self.currentPithosAccount = [pithosAccounts objectAtIndex:0];
+ self.pithosBrowserController.pithosAccountManager = currentPithosAccount;
- [self authenticateWithAuthUser:[[userDefaultsController values] valueForKey:@"authUser"]
- authToken:[[userDefaultsController values] valueForKey:@"authToken"]];
+ if (currentPithosAccount.active) {
+ [self savePithosAccounts:self];
+ [self showPithosBrowser:self];
+ self.pithosBrowserController.pithos = currentPithosAccount.pithos;
+ } else {
+ // XXX maybe call specifically to go to new account tab
+ [self showPithosPreferences:self];
+ }
+
+ syncTimer = [NSTimer scheduledTimerWithTimeInterval:syncTimeInterval
+ target:self
+ selector:@selector(sync)
+ userInfo:nil
+ repeats:YES];
+ [syncTimer fire];
+
+ @synchronized(self) {
+ self.checkForUpdatesNotRunning = YES;
+ }
+ [self checkForUpdates];
}
// Based on: http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/
// and: http://www.cocoadev.com/index.pl?ThumbnailImages
- (void)awakeFromNib {
- NSImage *sourceImage = [NSImage imageNamed:NSImageNameFolder];
+ 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];
+
+ self.alwaysNo = NO;
}
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent {
NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
NSString *host = [url host];
NSString *query = [url query];
- NSLog(@"host : '%@', query: '%@'", host, query);
+ PithosAccount *pithosAccount = [pithosAccountsDictionary objectForKey:[ASIPithosRequest decodeFromPercentEscape:[url lastPathComponent]]];
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
- if ([host isEqualToString:[NSString stringWithFormat:@"%@_%d", [processInfo processName], [processInfo processIdentifier]]] && query) {
+ if ([host isEqualToString:[NSString stringWithFormat:@"%d", [processInfo processIdentifier]]] && pithosAccount && query) {
// user=
NSString *authUser;
NSRange userRange = [query rangeOfString:@"user=" options:NSCaseInsensitiveSearch];
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
- NSLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken);
+ DLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken);
if ([authUser length] && [authToken length]) {
- [[userDefaultsController values] setValue:authUser forKey:@"authUser"];
- [[userDefaultsController values] setValue:authToken forKey:@"authToken"];
-
- [self authenticateWithAuthUser:authUser authToken:authToken];
+ [pithosAccount authenticateWithServerURL:nil authUser:authUser authToken:authToken];
+ [self savePithosAccounts:self];
+ if (self.pithosPreferencesController && [self.pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount]) {
+ self.pithosPreferencesController.authUser = pithosAccount.authUser;
+ self.pithosPreferencesController.authToken = pithosAccount.authToken;
+ }
+ self.activated = YES;
+ if ([pithosAccount isEqualTo:currentPithosAccount]) {
+ [self showPithosBrowser:self];
+ self.pithosBrowserController.pithos = pithosAccount.pithos;
+ }
}
// XXX else maybe show an error message?
}
// XXX else maybe show an error message?
}
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+ [self savePithosAccounts:self];
+ if ([self.pithosBrowserController operationsPending]) {
+ 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"];
+ [alert addButtonWithTitle:@"Cancel"];
+ NSInteger choice = [alert runModal];
+ if (choice == NSAlertSecondButtonReturn)
+ return NSTerminateCancel;
+ }
+ if (loginItems) {
+ LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(), (CFStringRef)NSDefaultRunLoopMode, LSSharedFileListChanged, (__bridge void *)(self));
+ CFRelease(loginItems);
+ }
+ return NSTerminateNow;
+}
+
+#pragma mark -
+#pragma mark Callbacks
+
+- (void)loginItemsChanged {
+ NSURL *appURL = [[NSBundle mainBundle] bundleURL];
+ LSSharedFileListItemRef appItem = NULL;
+ NSArray *snapshot = (__bridge_transfer NSArray *)(LSSharedFileListCopySnapshot(loginItems, NULL));
+ for (id itemObject in snapshot) {
+ LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject;
+ UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
+ CFURLRef currentItemURL = NULL;
+ LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
+ if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(appURL))) {
+ CFRelease(currentItemURL);
+ appItem = item;
+ break;
+ }
+ if (currentItemURL)
+ CFRelease(currentItemURL);
+ }
+
+ if (appItem && (!openAtLogin || !openAtLoginEnabled))
+ self.openAtLogin = YES;
+ else if (!appItem && (openAtLogin || !openAtLoginEnabled))
+ self.openAtLogin = NO;
+}
+
+void LSSharedFileListChanged(LSSharedFileListRef inList, void *context) {
+ pithos_macosAppDelegate *self = (__bridge id)context;
+ [self loginItemsChanged];
+}
+
+#pragma mark -
+#pragma mark Properties
+
+- (PithosBrowserController *)pithosBrowserController {
+ if (!pithosBrowserController) {
+ pithosBrowserController = [[PithosBrowserController alloc] init];
+ }
+ return pithosBrowserController;
+}
+
+- (PithosPreferencesController *)pithosPreferencesController {
+ if (!pithosPreferencesController) {
+ pithosPreferencesController = [[PithosPreferencesController alloc] init];
+ }
+ return pithosPreferencesController;
+}
+
+- (void)setOpenAtLogin:(BOOL)anOpenAtLogin {
+ if (!openAtLoginEnabled) {
+ openAtLogin = anOpenAtLogin;
+ } else if (anOpenAtLogin != openAtLogin) {
+ NSURL *appURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
+ LSSharedFileListItemRef appItem = NULL;
+ NSArray *snapshot = (__bridge_transfer NSArray *)(LSSharedFileListCopySnapshot(loginItems, NULL));
+ for (id itemObject in snapshot) {
+ LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject;
+ UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
+ CFURLRef currentItemURL = NULL;
+ LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
+ if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(appURL))) {
+ CFRelease(currentItemURL);
+ appItem = item;
+ break;
+ }
+ if (currentItemURL)
+ CFRelease(currentItemURL);
+ }
+
+ if (anOpenAtLogin) {
+ if (!appItem)
+ LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, (__bridge CFURLRef)appURL, NULL, NULL);
+ openAtLogin = YES;
+ } else {
+ if (appItem)
+ LSSharedFileListItemRemove(loginItems, appItem);
+ openAtLogin = NO;
+ }
+ }
+}
+
#pragma mark -
-#pragma Actions
+#pragma mark NSMenuDelegate
+
+- (void)menuNeedsUpdate:(NSMenu *)menu {
+ NSMenuItem *menuItem;
+ [menu removeAllItems];
+ if ([menu isEqualTo:accountsMenu]) {
+ [menu setAutoenablesItems:NO];
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ menuItem = [[NSMenuItem alloc] initWithTitle:pithosAccount.name
+ action:@selector(menuChangePithosAccount:)
+ keyEquivalent:@""];
+ [menuItem setRepresentedObject:pithosAccount];
+ [menuItem setEnabled:pithosAccount.active];
+ [menuItem setState:((pithosAccount.active && [currentPithosAccount isEqualTo:pithosAccount]) ? NSOnState : NSOffState)];
+ [menu addItem:menuItem];
+ }
+ } else if ([menu isEqualTo:lastSyncMenu]) {
+ NSString *menuItemTitle;
+ [menu setAutoenablesItems:NO];
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ menuItemTitle = [NSString stringWithFormat:@"%@: %@",
+ pithosAccount.name,
+ [[[LastCompletedSyncTransformer alloc] init] transformedValue:pithosAccount.syncLastCompleted]];
+ if ([pithosAccount isEqualTo:syncPithosAccount] && [pithosAccount.syncDaemon isSyncing])
+ menuItemTitle = [menuItemTitle stringByAppendingString:@" (syncing)"];
+// menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle
+// action:@selector(menuChangeSyncActive:)
+// keyEquivalent:@""] autorelease];
+// [menuItem setRepresentedObject:pithosAccount];
+// [menuItem setEnabled:pithosAccount.active];
+// [menuItem setState:((pithosAccount.active && pithosAccount.syncActive) ? NSOnState : NSOffState)];
+ 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"
+ action:@selector(sync)
+ keyEquivalent:@""]];
+ }
+}
+
+#pragma mark -
+#pragma mark Actions
- (IBAction)showPithosBrowser:(id)sender {
- [pithosBrowserController showWindow:sender];
- [[pithosBrowserController window] makeKeyAndOrderFront:sender];
+ if (!activated)
+ return;
+ [self.pithosBrowserController showWindow:sender];
+ [[self.pithosBrowserController window] makeKeyAndOrderFront:sender];
[NSApp activateIgnoringOtherApps:YES];
}
- (IBAction)showPithosPreferences:(id)sender {
- [pithosPreferencesController showWindow:sender];
- [[pithosPreferencesController window] makeKeyAndOrderFront:sender];
+ [self.pithosPreferencesController showWindow:sender];
+ [[self.pithosPreferencesController window] makeKeyAndOrderFront:sender];
[NSApp activateIgnoringOtherApps:YES];
}
-- (IBAction)aboutPithos:(id)sender {
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:self.aboutURL]];
+- (IBAction)showPithosAbout:(id)sender {
+ [NSApp orderFrontStandardAboutPanel:sender];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+- (void)sync {
+ if (!activated || ![pithosAccounts count])
+ return;
+ NSUInteger syncIndex;
+ BOOL syncPithosAccountFound = [pithosAccounts containsObject:syncPithosAccount];
+ if (syncPithosAccountFound)
+ syncIndex = [pithosAccounts indexOfObject:syncPithosAccount];
+
+ PithosAccount *singleSyncPithosAccount = nil;
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ if (!singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
+ singleSyncPithosAccount = pithosAccount;
+ } else if (singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
+ singleSyncPithosAccount = nil;
+ break;
+ }
+ }
+
+ if (syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
+ // An active syncDaemon was previously syncing
+ if (singleSyncPithosAccount && [singleSyncPithosAccount isEqualTo:syncPithosAccount]) {
+ // It's the only one, sync again
+ [syncPithosAccount.syncDaemon startDaemon];
+ [syncPithosAccount.syncDaemon sync];
+ return;
+ } else if ([syncPithosAccount.syncDaemon isSyncing]) {
+ // It's still syncing, mark it as late and return
+ [syncPithosAccount.syncDaemon syncLate];
+ return;
+ }
+ }
+ PithosAccount *newSyncPithosAccount = nil;
+ if (syncPithosAccountFound) {
+ for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(syncIndex + 1, [pithosAccounts count] - syncIndex - 1)]]) {
+ if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
+ newSyncPithosAccount = pithosAccount;
+ break;
+ }
+ }
+ if (!newSyncPithosAccount) {
+ for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, syncIndex)]]) {
+ if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
+ newSyncPithosAccount = pithosAccount;
+ break;
+ }
+ }
+ }
+ } else {
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
+ newSyncPithosAccount = pithosAccount;
+ break;
+ }
+ }
+ }
+ if (newSyncPithosAccount) {
+ // A different syncDaemon is found, sync it
+ self.syncPithosAccount = newSyncPithosAccount;
+ [syncPithosAccount.syncDaemon startDaemon];
+ [syncPithosAccount.syncDaemon sync];
+ } else if (syncPithosAccountFound && syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
+ [syncPithosAccount.syncDaemon startDaemon];
+ [syncPithosAccount.syncDaemon sync];
+ } else {
+ self.syncPithosAccount = nil;
+ }
+}
+
+- (void)savePithosAccounts:(id)sender {
+ [userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:pithosAccounts] forKey:@"pithosAccounts"];
+ [userDefaults synchronize];
+}
+
+- (void)removedPithosAccount:(PithosAccount *)removedPithosAccount {
+ if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
+ for (PithosAccount *pithosAccount in pithosAccounts) {
+ if (pithosAccount.active) {
+ self.currentPithosAccount = pithosAccount;
+ self.pithosBrowserController.pithosAccountManager = currentPithosAccount;
+ self.pithosBrowserController.pithos = currentPithosAccount.pithos;
+ break;
+ }
+ }
+ if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
+ self.activated = NO;
+ [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 Authentication
-
-- (void)authenticateWithAuthUser:(NSString *)authUser authToken:(NSString *)authToken {
- NSLog(@"Authentication - storageURLPrefix:%@, authUser:%@, authToken:%@", storageURLPrefix, authUser, authToken);
- if ([authUser length] && [authToken length]) {
- [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
- [ASIPithosRequest setAuthURL:storageURLPrefix];
- [ASIPithosRequest setStorageURLPrefix:storageURLPrefix];
- [ASIPithosRequest setAuthUser:authUser];
- [ASIPithosRequest setAuthToken:authToken];
- [ASIPithosRequest setPublicURLPrefix:publicURLPrefix];
-
- [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosAuthenticationCredentialsUpdated" object:self];
+#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
+
+- (void)menuChangePithosAccount:(NSMenuItem *)sender {
+ PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
+ if (!pithosAccount.active)
+ return;
+ if (![currentPithosAccount isEqualTo:pithosAccount] && [pithosAccounts containsObject:pithosAccount]) {
+ if ([self.pithosBrowserController operationsPending]) {
+ 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"];
+ [alert addButtonWithTitle:@"Cancel"];
+ NSInteger choice = [alert runModal];
+ if (choice == NSAlertSecondButtonReturn)
+ return;
+ }
+ self.currentPithosAccount = pithosAccount;
+ self.pithosBrowserController.pithosAccountManager = currentPithosAccount;
+ [self showPithosBrowser:self];
+ self.pithosBrowserController.pithos = currentPithosAccount.pithos;
+ }
+}
+
+//- (void)menuChangeSyncActive:(NSMenuItem *)sender {
+// PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
+// if (!pithosAccount.active)
+// return;
+// pithosAccount.syncActive = !pithosAccount.syncActive;
+// if (self.pithosPreferencesController && [self.pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount])
+// self.pithosPreferencesController.syncActive = pithosAccount.syncActive;
+// [self savePithosAccounts:self];
+//}
+
+- (IBAction)menuCheckForUpdates:(NSMenuItem *)sender {
+ @synchronized(self) {
+ checkForUpdatesCalledFromMenu = YES;
}
+ [self checkForUpdates];
}
@end