Skip to content

Commit

Permalink
Launch app at startup option
Browse files Browse the repository at this point in the history
  • Loading branch information
alexking committed Nov 19, 2013
1 parent 045aab4 commit b806d20
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 26 deletions.
6 changes: 6 additions & 0 deletions StatusThing.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
64B497C2183735DD007BB1D0 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64B497C1183735DD007BB1D0 /* Sparkle.framework */; };
64B497C5183737F8007BB1D0 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 64B497C1183735DD007BB1D0 /* Sparkle.framework */; };
64B497C718373E5D007BB1D0 /* sparkle-public-key.pem in Resources */ = {isa = PBXBuildFile; fileRef = 64B497C618373E5D007BB1D0 /* sparkle-public-key.pem */; };
64B497CA1839D035007BB1D0 /* AKLaunchItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 64B497C91839D035007BB1D0 /* AKLaunchItem.m */; };
B69F5283100C4CBD930BB43F /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABA0628C4E3D4093B823CE66 /* libPods.a */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -75,6 +76,8 @@
64A901161833398400D91489 /* AKTestSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AKTestSettings.m; sourceTree = "<group>"; };
64B497C1183735DD007BB1D0 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
64B497C618373E5D007BB1D0 /* sparkle-public-key.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sparkle-public-key.pem"; sourceTree = "<group>"; };
64B497C81839D035007BB1D0 /* AKLaunchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AKLaunchItem.h; sourceTree = "<group>"; };
64B497C91839D035007BB1D0 /* AKLaunchItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AKLaunchItem.m; sourceTree = "<group>"; };
ABA0628C4E3D4093B823CE66 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -148,6 +151,8 @@
children = (
64490A861832AF6F006F8D10 /* AKSettings.h */,
64490A871832AF6F006F8D10 /* AKSettings.m */,
64B497C81839D035007BB1D0 /* AKLaunchItem.h */,
64B497C91839D035007BB1D0 /* AKLaunchItem.m */,
6415A5B7182F4E1300EEBAA2 /* AKAppDelegate.h */,
6415A5B8182F4E1300EEBAA2 /* AKAppDelegate.m */,
6415A5BA182F4E1300EEBAA2 /* MainMenu.xib */,
Expand Down Expand Up @@ -344,6 +349,7 @@
6415A5B9182F4E1300EEBAA2 /* AKAppDelegate.m in Sources */,
64490A881832AF6F006F8D10 /* AKSettings.m in Sources */,
6415A5B2182F4E1300EEBAA2 /* main.m in Sources */,
64B497CA1839D035007BB1D0 /* AKLaunchItem.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
6 changes: 6 additions & 0 deletions StatusThing/AKAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import <AKSmartThings/AKSmartThings.h>
#import <CocoaHTTPServer/HTTPServer.h>
#import "AKSettings.h"
#import "AKLaunchItem.h"

@interface AKAppDelegate : NSObject <NSApplicationDelegate, AKSmartThingsDelegate, NSTextDelegate>

Expand All @@ -11,6 +12,7 @@
// Library Instances
@property (strong) AKSmartThings *things;
@property (strong) AKSettings *settings;
@property (strong) AKLaunchItem *launch;

// State management
@property NSMutableArray *items;
Expand Down Expand Up @@ -41,6 +43,10 @@
- (IBAction)preferencesTemperatureScale:(NSPopUpButton *)sender;
- (IBAction)preferencesTemperatureSensor:(NSPopUpButton *)sender;

@property (weak) IBOutlet NSButton *preferencesStartAtLogin;
- (IBAction)preferencesStartAtLogin:(NSButton *)sender;


@property (weak) IBOutlet NSImageView *preferencesClientIdStatus;
@property (weak) IBOutlet NSImageView *preferencesClientSecretStatus;

Expand Down
86 changes: 79 additions & 7 deletions StatusThing/AKAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
// Settings
self.settings = [[AKSettings alloc] init];

// Launch
self.launch = [[AKLaunchItem alloc] init];

// Setup
self.items = [[NSMutableArray alloc] init];
self.preferencesTemperatureSensorTitleToId = [[NSMutableDictionary alloc] init];
Expand Down Expand Up @@ -158,13 +161,20 @@ - (void) refreshMenu {
[self.statusMenu removeAllItems];

// If we're not showing the temperature in the status bar, show it in the menu
if (![self.settings showTemperatureInCelsius])
if (![self.settings showTemperatureInStatusBar] && [self temperaturesForDisplay] != nil)
{

[self.statusMenu addItem: [[NSMenuItem alloc] initWithTitle: [self temperatureInScale]
action: nil
keyEquivalent: @""]];

for (NSDictionary *temperature in [self temperaturesForDisplay]) {



[self.statusMenu addItem: [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: @"%@%@", [temperature objectForKey: @"temperature"], [temperature objectForKey: @"name"] ]
action: nil
keyEquivalent: @""]];


}

[self.statusMenu addItem: [NSMenuItem separatorItem]];

}
Expand Down Expand Up @@ -242,6 +252,47 @@ - (void) refreshStatusItem

}

- (NSArray *)temperaturesForDisplay
{
NSMutableArray *temperatures = [[NSMutableArray alloc] init];

// If we don't have any temperatures yet
if (self.temperatures == nil)
{
return nil;
}

// Each temperature
for (NSDictionary *sensor in self.temperatures) {

NSNumber *temperatureNumber = [sensor objectForKey: @"value"];

if (temperatureNumber == nil)
{
continue;
}

// Convert to long
long temperature = [temperatureNumber longValue];

// Convert to celsius if requested
if ([self.settings showTemperatureInCelsius])
{
temperature = (temperature - 32) * (5.0 / 9.0);
}

// Add a dictionary to our array
[temperatures addObject: [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat: @"%ld°", temperature], @"temperature",
[sensor objectForKey: @"name"], @"name",
nil]];

}

return temperatures;

}

- (NSString *) temperatureInScale
{

Expand Down Expand Up @@ -328,8 +379,6 @@ - (void) debugFound: (id)json
/*! Request an update from server */
- (void) requestUpdateFromServer
{

NSLog(@"Checking with %@", self.settings.accessToken);

if (self.settings.accessToken)
{
Expand Down Expand Up @@ -497,6 +546,14 @@ - (void)refreshPreferences

}

// Start at login?
if ([self.launch loginItemExists])
{
[self.preferencesStartAtLogin setState: NSOnState];
} else {
[self.preferencesStartAtLogin setState: NSOffState];
}

/***************
| Account Tab *
**************/
Expand Down Expand Up @@ -683,6 +740,20 @@ - (IBAction)preferencesTemperatureSensor:(NSPopUpButton *)sender
[self refreshInterface];
}

- (IBAction)preferencesStartAtLogin:(NSButton *)sender {

if ([sender state] == NSOffState)
{
[self.launch removeLoginItem];
} else {
[self.launch addLoginItem];
}



}


- (IBAction)preferencesViewAbout:(NSButton *)sender {
[[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: @"https://github.com/alexking/StatusThing/wiki/About-Page"]];
}
Expand All @@ -697,4 +768,5 @@ - (void)applicationWillTerminate:(NSNotification *)notification
}



@end
13 changes: 13 additions & 0 deletions StatusThing/AKLaunchItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>

@interface AKLaunchItem : NSObject

-(bool) loginItemExists;
-(void) addLoginItem;
-(void) removeLoginItem;

@property (strong) NSURL *applicationURL;

@end
139 changes: 139 additions & 0 deletions StatusThing/AKLaunchItem.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Handle launching at login
*
* Based on the example code from -
* http://cocoatutorial.grapewave.com/2010/02/creating-andor-removing-a-login-item
*
*/

#import "AKLaunchItem.h"

@implementation AKLaunchItem

/*! Init using the default main bundle application URL */
- (id)init
{
return [self initWithApplicationURL: [NSURL fileURLWithPath: [[NSBundle mainBundle] bundlePath]]];
}

/*! Init using a custom application URL */
- (id)initWithApplicationURL: (NSURL *)url
{
self = [super init];
if (self) {
self.applicationURL = url;
}
return self;
}


-(void) addLoginItem
{

// Refuse to add a login item that already exists
if ([self loginItemExists])
{
NSLog(@"Login item for this application already exists");
return;
}

// Find the URL of the app as a CFURLRef
NSURL *appURL = self.applicationURL;
CFURLRef appURLRef = (__bridge CFURLRef)appURL;

// Find the list of login items
LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);

// Make sure we found some items
if (loginItems)
{
// Insert our login item
LSSharedFileListItemRef loginItemRef = LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemLast, NULL, NULL, appURLRef, NULL, NULL);

// Release that login item
if (loginItemRef)
{
CFRelease(loginItemRef);
}

// We know that it exists, so we may release it
CFRelease(loginItems);
}

}

-(bool) loginItemExists
{
return [self findLoginItemAndRemove: NO];
}

-(void) removeLoginItem
{
[self findLoginItemAndRemove: YES];

}

-(bool) findLoginItemAndRemove:(bool)remove
{

// Find the URL of the app
NSURL *appURL = self.applicationURL;

// Find the list of login items
LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);

// Make sure we found some items
if (loginItemsRef)
{



// Define some variables we'll need
UInt32 snapshotSeed;

// Find an array of login items (transfering the ownership to our ARC managed NSArray)
NSArray *loginItems = (__bridge_transfer NSArray *) LSSharedFileListCopySnapshot(loginItemsRef, &snapshotSeed);

// Loop through the items
for (id loginItem in loginItems)
{

// Convert the item into a LSSharedFileListItemRef (leaving ownership with ARC managed loginItem)
LSSharedFileListItemRef loginItemRef = (__bridge LSSharedFileListItemRef) loginItem;


// Try to resolve the item
CFURLRef itemURLRef;
if (LSSharedFileListItemResolve(loginItemRef, 0, &itemURLRef, NULL) == noErr)
{

// Check if this is our item
NSURL *itemURL = (__bridge NSURL*)itemURLRef;
if ([[appURL path] isEqualToString: [itemURL path]])
{
if (remove)
{
LSSharedFileListItemRemove(loginItemsRef, loginItemRef);
} else {
return YES;
}
}

// Release the URL ref, since we never transfered ownership to ARC
CFRelease(itemURLRef);

}

}

// Release the login items ref
CFRelease(loginItemsRef);


}

return NO;

}

@end
Loading

0 comments on commit b806d20

Please sign in to comment.