From dcad77919ff5d188daf1bf07e545d3703811b4dd Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Thu, 1 Dec 2016 13:50:59 -0500 Subject: Add a checkbox to the UI for whether to start at login This will enable and disable the daemon and set whether or not it starts at login. --- Low Battery Yup/AppDelegate.h | 1 + Low Battery Yup/en.lproj/MainMenu.xib | 70 ++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Low Battery Yup/AppDelegate.h b/Low Battery Yup/AppDelegate.h index 3998e46..395ce9a 100644 --- a/Low Battery Yup/AppDelegate.h +++ b/Low Battery Yup/AppDelegate.h @@ -13,6 +13,7 @@ @interface AppDelegate : NSObject { IBOutlet NSWindow *window; IBOutlet ShortcutView *_shortcut_view; + IBOutlet NSButton *_start_at_login; } @end diff --git a/Low Battery Yup/en.lproj/MainMenu.xib b/Low Battery Yup/en.lproj/MainMenu.xib index 4b01316..e649cab 100644 --- a/Low Battery Yup/en.lproj/MainMenu.xib +++ b/Low Battery Yup/en.lproj/MainMenu.xib @@ -11,6 +11,8 @@ 2844 + NSButton + NSButtonCell NSCustomObject NSCustomView NSMenu @@ -1311,9 +1313,45 @@ {{84, 83}, {313, 19}} + _NS:9 ShortcutView + + + 268 + {{82, 32}, {104, 18}} + + + _NS:9 + YES + + -2080374784 + 268435456 + Start at login + + LucidaGrande + 13 + 1044 + + _NS:9 + + 1211912448 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + NO + {480, 185} @@ -2022,6 +2060,14 @@ 541 + + + _start_at_login + + + + 544 + @@ -2548,6 +2594,7 @@ + @@ -3029,6 +3076,19 @@ + + 542 + + + + + + + + 543 + + + @@ -3175,6 +3235,8 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3194,7 +3256,7 @@ - 541 + 544 @@ -3203,6 +3265,7 @@ NSObject ShortcutView + NSButton MASShortcutView NSTextField NSWindow @@ -3212,6 +3275,10 @@ _shortcut_view ShortcutView + + _start_at_login + NSButton + customShortcutView MASShortcutView @@ -3255,6 +3322,7 @@ {11, 11} {10, 3} + {15, 15} -- cgit v1.2.3 From 319dd672e1c75f39bcb9239117e520513da6609a Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Thu, 1 Dec 2016 13:51:58 -0500 Subject: AppDelegate.m: Move ShortcutView initialization into its own method Keep the code more organised by defining a name for this functionality since we want to add some additional code here to handle the "Start at login" checkbox. --- Low Battery Yup/AppDelegate.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Low Battery Yup/AppDelegate.m b/Low Battery Yup/AppDelegate.m index 83d03ae..1c77f41 100644 --- a/Low Battery Yup/AppDelegate.m +++ b/Low Battery Yup/AppDelegate.m @@ -17,6 +17,11 @@ } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + [self initializeShortcutView]; +} + +- (void)initializeShortcutView { NSDictionary *saved_shortcut; if ((saved_shortcut = [[NSUserDefaults standardUserDefaults] objectForKey:kPreferenceGlobalShortcut])) { -- cgit v1.2.3 From 055471fad0187e654302034a0875a417e73e089f Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 12:57:06 -0500 Subject: AppDelegate.h: Add `initializeShortcutView` Add the method to the header file from the original commit in 319dd672e1c75f39bcb9239117e520513da6609a. --- Low Battery Yup/AppDelegate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Low Battery Yup/AppDelegate.h b/Low Battery Yup/AppDelegate.h index 395ce9a..cc38038 100644 --- a/Low Battery Yup/AppDelegate.h +++ b/Low Battery Yup/AppDelegate.h @@ -16,4 +16,6 @@ IBOutlet NSButton *_start_at_login; } +- (void)initializeShortcutView; + @end -- cgit v1.2.3 From a77a053f90a7b2588dbaabedbf25f908680f2f30 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 13:00:19 -0500 Subject: Add "Start at login" checkbox that [un]installs launch agent A new checkbox in the UI that asks whether the app should start at login. Checking and unchecking the box moves a LaunchAgent plist into and out of `~/Library/LaunchAgents/`. This plist file will define instructions to start the daemon on login. Also add a `DaemonLauncher` class that will launch or quit the daemon when the checkbox is clicked. Bug: Currently the app always starts with the checkbox checked. That's not what should happen. Instead, we should save the checkbox value to `NSUserDefaults` so that it has the previous value when the program is launched. --- Low Battery Yup.d.xcodeproj/project.pbxproj | 16 +++++++ Low Battery Yup/AppDelegate.h | 4 ++ Low Battery Yup/AppDelegate.m | 21 +++++++++ Low Battery Yup/DaemonLauncher.h | 13 ++++++ Low Battery Yup/DaemonLauncher.m | 13 ++++++ Low Battery Yup/LaunchAgentManager.h | 20 +++++++++ Low Battery Yup/LaunchAgentManager.m | 52 ++++++++++++++++++++++ ...om.teddywing.Low-Battery-Yup.StartAtLogin.plist | 5 +++ Low Battery Yup/en.lproj/MainMenu.xib | 23 +++++++++- 9 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 Low Battery Yup/DaemonLauncher.h create mode 100644 Low Battery Yup/DaemonLauncher.m create mode 100644 Low Battery Yup/LaunchAgentManager.h create mode 100644 Low Battery Yup/LaunchAgentManager.m create mode 100644 Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist diff --git a/Low Battery Yup.d.xcodeproj/project.pbxproj b/Low Battery Yup.d.xcodeproj/project.pbxproj index f1c9910..b625f3b 100644 --- a/Low Battery Yup.d.xcodeproj/project.pbxproj +++ b/Low Battery Yup.d.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ D123F5A81DDF9D2400A27B7A /* DDHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = D123F5A71DDF9D2400A27B7A /* DDHotKeyCenter.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + D131EB381DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist in Resources */ = {isa = PBXBuildFile; fileRef = D131EB371DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist */; }; D15D90B71DF0465E001700CD /* ShortcutView.m in Sources */ = {isa = PBXBuildFile; fileRef = D15D90B61DF0465E001700CD /* ShortcutView.m */; }; D1871D071DE094AB00B8030D /* DDHotKeyTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D1871D061DE094AB00B8030D /* DDHotKeyTextField.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; D1871D081DE094C200B8030D /* DDHotKeyUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D1A37AF01DE001770022434D /* DDHotKeyUtilities.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; @@ -21,6 +22,8 @@ D18C94C51DDC355400E03F87 /* Mouse.m in Sources */ = {isa = PBXBuildFile; fileRef = D18C94C41DDC355400E03F87 /* Mouse.m */; }; D195AE5F1DDC776000A53A18 /* MASShortcut.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D195AE5A1DDC774300A53A18 /* MASShortcut.framework */; }; D195AE601DDC776F00A53A18 /* MASShortcut.framework in Resources */ = {isa = PBXBuildFile; fileRef = D195AE5A1DDC774300A53A18 /* MASShortcut.framework */; }; + D19DF20F1DF1AD3D0094C50F /* LaunchAgentManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D19DF20E1DF1AD3D0094C50F /* LaunchAgentManager.m */; }; + D19DF2121DF1AD480094C50F /* DaemonLauncher.m in Sources */ = {isa = PBXBuildFile; fileRef = D19DF2111DF1AD480094C50F /* DaemonLauncher.m */; }; D1A37AEE1DE0012C0022434D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1A37AED1DE0012C0022434D /* Carbon.framework */; }; D1A37AF11DE001770022434D /* DDHotKeyUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D1A37AF01DE001770022434D /* DDHotKeyUtilities.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; D1F809E11DDC6AA0001671E9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D18C94A21DDC33CF00E03F87 /* Cocoa.framework */; }; @@ -58,6 +61,7 @@ /* Begin PBXFileReference section */ D123F5A61DDF9D2400A27B7A /* DDHotKeyCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDHotKeyCenter.h; path = DDHotKey/DDHotKeyCenter.h; sourceTree = ""; }; D123F5A71DDF9D2400A27B7A /* DDHotKeyCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DDHotKeyCenter.m; path = DDHotKey/DDHotKeyCenter.m; sourceTree = ""; }; + D131EB371DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.teddywing.Low-Battery-Yup.StartAtLogin.plist"; sourceTree = ""; }; D15D90B51DF0465E001700CD /* ShortcutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShortcutView.h; sourceTree = ""; }; D15D90B61DF0465E001700CD /* ShortcutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShortcutView.m; sourceTree = ""; }; D1871D051DE094AB00B8030D /* DDHotKeyTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDHotKeyTextField.h; path = DDHotKey/DDHotKeyTextField.h; sourceTree = ""; }; @@ -78,6 +82,10 @@ D18C94C41DDC355400E03F87 /* Mouse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Mouse.m; sourceTree = ""; }; D195AE4F1DDC774200A53A18 /* MASShortcut.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MASShortcut.xcodeproj; path = MASShortcut/MASShortcut.xcodeproj; sourceTree = ""; }; D19DF1F41DF09CF30094C50F /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; + D19DF20D1DF1AD3D0094C50F /* LaunchAgentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchAgentManager.h; sourceTree = ""; }; + D19DF20E1DF1AD3D0094C50F /* LaunchAgentManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LaunchAgentManager.m; sourceTree = ""; }; + D19DF2101DF1AD480094C50F /* DaemonLauncher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DaemonLauncher.h; sourceTree = ""; }; + D19DF2111DF1AD480094C50F /* DaemonLauncher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DaemonLauncher.m; sourceTree = ""; }; D1A37AED1DE0012C0022434D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; D1A37AEF1DE001770022434D /* DDHotKeyUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDHotKeyUtilities.h; path = DDHotKey/DDHotKeyUtilities.h; sourceTree = ""; }; D1A37AF01DE001770022434D /* DDHotKeyUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DDHotKeyUtilities.m; path = DDHotKey/DDHotKeyUtilities.m; sourceTree = ""; }; @@ -207,6 +215,10 @@ D195AE4F1DDC774200A53A18 /* MASShortcut.xcodeproj */, D1F809EE1DDC6AA0001671E9 /* AppDelegate.h */, D1F809EF1DDC6AA0001671E9 /* AppDelegate.m */, + D19DF20D1DF1AD3D0094C50F /* LaunchAgentManager.h */, + D19DF20E1DF1AD3D0094C50F /* LaunchAgentManager.m */, + D19DF2101DF1AD480094C50F /* DaemonLauncher.h */, + D19DF2111DF1AD480094C50F /* DaemonLauncher.m */, D19DF1F41DF09CF30094C50F /* Constants.h */, D15D90B51DF0465E001700CD /* ShortcutView.h */, D15D90B61DF0465E001700CD /* ShortcutView.m */, @@ -224,6 +236,7 @@ D1F809E81DDC6AA0001671E9 /* main.m */, D1F809EA1DDC6AA0001671E9 /* Low Battery Yup-Prefix.pch */, D1F809EB1DDC6AA0001671E9 /* Credits.rtf */, + D131EB371DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist */, ); name = "Supporting Files"; sourceTree = ""; @@ -346,6 +359,7 @@ D1F809ED1DDC6AA0001671E9 /* Credits.rtf in Resources */, D1F809F31DDC6AA0001671E9 /* MainMenu.xib in Resources */, D195AE601DDC776F00A53A18 /* MASShortcut.framework in Resources */, + D131EB381DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -374,6 +388,8 @@ D1871D081DE094C200B8030D /* DDHotKeyUtilities.m in Sources */, D1871D091DE0955E00B8030D /* DDHotKeyCenter.m in Sources */, D15D90B71DF0465E001700CD /* ShortcutView.m in Sources */, + D19DF20F1DF1AD3D0094C50F /* LaunchAgentManager.m in Sources */, + D19DF2121DF1AD480094C50F /* DaemonLauncher.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Low Battery Yup/AppDelegate.h b/Low Battery Yup/AppDelegate.h index cc38038..4ae3e9c 100644 --- a/Low Battery Yup/AppDelegate.h +++ b/Low Battery Yup/AppDelegate.h @@ -9,13 +9,17 @@ #import #import #import "ShortcutView.h" +#import "LaunchAgentManager.h" @interface AppDelegate : NSObject { IBOutlet NSWindow *window; IBOutlet ShortcutView *_shortcut_view; IBOutlet NSButton *_start_at_login; + + LaunchAgentManager *_launchagent; } - (void)initializeShortcutView; +- (IBAction)performStartAtLogin:(id)sender; @end diff --git a/Low Battery Yup/AppDelegate.m b/Low Battery Yup/AppDelegate.m index 1c77f41..365b1bf 100644 --- a/Low Battery Yup/AppDelegate.m +++ b/Low Battery Yup/AppDelegate.m @@ -11,14 +11,25 @@ @implementation AppDelegate +- (id)init +{ + self = [super init]; + if (self) { + _launchagent = [[LaunchAgentManager alloc] init]; + } + return self; +} + - (void)dealloc { + [_launchagent release]; [super dealloc]; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [self initializeShortcutView]; + [self performStartAtLogin:self]; } - (void)initializeShortcutView @@ -33,6 +44,16 @@ } } +- (IBAction)performStartAtLogin:(id)sender +{ + if ([_start_at_login state] == NSOnState) { + [_launchagent install]; + } + else { + [_launchagent uninstall]; + } +} + - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { return YES; diff --git a/Low Battery Yup/DaemonLauncher.h b/Low Battery Yup/DaemonLauncher.h new file mode 100644 index 0000000..a62a256 --- /dev/null +++ b/Low Battery Yup/DaemonLauncher.h @@ -0,0 +1,13 @@ +// +// DaemonLauncher.h +// Low Battery Yup.d +// +// Created by TW on 12/2/16. +// Copyright (c) 2016 TW. All rights reserved. +// + +#import + +@interface DaemonLauncher : NSObject + +@end diff --git a/Low Battery Yup/DaemonLauncher.m b/Low Battery Yup/DaemonLauncher.m new file mode 100644 index 0000000..4c6449c --- /dev/null +++ b/Low Battery Yup/DaemonLauncher.m @@ -0,0 +1,13 @@ +// +// DaemonLauncher.m +// Low Battery Yup.d +// +// Created by TW on 12/2/16. +// Copyright (c) 2016 TW. All rights reserved. +// + +#import "DaemonLauncher.h" + +@implementation DaemonLauncher + +@end diff --git a/Low Battery Yup/LaunchAgentManager.h b/Low Battery Yup/LaunchAgentManager.h new file mode 100644 index 0000000..5a9fa44 --- /dev/null +++ b/Low Battery Yup/LaunchAgentManager.h @@ -0,0 +1,20 @@ +// +// LaunchAgentManager.h +// Low Battery Yup.d +// +// Created by TW on 12/2/16. +// Copyright (c) 2016 TW. All rights reserved. +// + +#import + +#define LAUNCH_AGENTS_PATH @"~/Library/LaunchAgents" + +@interface LaunchAgentManager : NSObject { + NSFileManager *_file_manager; +} + +- (BOOL)install; +- (BOOL)uninstall; + +@end diff --git a/Low Battery Yup/LaunchAgentManager.m b/Low Battery Yup/LaunchAgentManager.m new file mode 100644 index 0000000..fd75795 --- /dev/null +++ b/Low Battery Yup/LaunchAgentManager.m @@ -0,0 +1,52 @@ +// +// LaunchAgentManager.m +// Low Battery Yup.d +// +// Created by TW on 12/2/16. +// Copyright (c) 2016 TW. All rights reserved. +// + +#import "LaunchAgentManager.h" + +@implementation LaunchAgentManager + +- (id)init +{ + self = [super init]; + if (self) { + _file_manager = [NSFileManager defaultManager]; + } + return self; +} + +- (BOOL)install +{ + NSBundle *main_bundle = [NSBundle mainBundle]; + NSURL *launchagents_url = [NSURL fileURLWithPath: + [[LAUNCH_AGENTS_PATH stringByAppendingString:@"/com.teddywing.Low-Battery-Yup.StartAtLogin.plist"] stringByExpandingTildeInPath] + isDirectory:YES]; + + NSError *error; + BOOL success = [_file_manager copyItemAtURL: + [main_bundle URLForResource:@"com.teddywing.Low-Battery-Yup.StartAtLogin" withExtension:@"plist"] + toURL:launchagents_url + error:&error]; + + if (!success) { + NSLog(@"%@", error); + } + + return success; +} + +- (BOOL)uninstall +{ + return [[NSWorkspace sharedWorkspace] + performFileOperation:NSWorkspaceRecycleOperation + source:[LAUNCH_AGENTS_PATH stringByExpandingTildeInPath] + destination:@"" + files:[NSArray arrayWithObject:@"com.teddywing.Low-Battery-Yup.StartAtLogin.plist"] + tag:nil]; +} + +@end diff --git a/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist b/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/Low Battery Yup/en.lproj/MainMenu.xib b/Low Battery Yup/en.lproj/MainMenu.xib index e649cab..5e48c4e 100644 --- a/Low Battery Yup/en.lproj/MainMenu.xib +++ b/Low Battery Yup/en.lproj/MainMenu.xib @@ -1358,7 +1358,7 @@ - {{0, 0}, {2560, 1578}} + {{0, 0}, {1440, 878}} {480, 207} {480, 207} YES @@ -2068,6 +2068,14 @@ 544 + + + performStartAtLogin: + + + + 545 + @@ -3256,13 +3264,24 @@ - 544 + 545 AppDelegate NSObject + + performStartAtLogin: + id + + + performStartAtLogin: + + performStartAtLogin: + id + + ShortcutView NSButton -- cgit v1.2.3 From fa5011f9aa660ed4d076628dfb5caf8233b94991 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 13:37:24 -0500 Subject: MainMenu.xib: Bind "Start at login" checkbox to NSUserDefaultsController Add a Key-Value Binding in Interface Builder to `NSUserDefaultsController` so that the checkbox value gets persisted between launches of the app. This fixes the bug mentioned in a77a053f90a7b2588dbaabedbf25f908680f2f30 such that now unchecking the box and closing the app will result in the checkbox being unchecked on the next launch. Wow, that was super easy! --- Low Battery Yup/en.lproj/MainMenu.xib | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Low Battery Yup/en.lproj/MainMenu.xib b/Low Battery Yup/en.lproj/MainMenu.xib index 5e48c4e..54cde7c 100644 --- a/Low Battery Yup/en.lproj/MainMenu.xib +++ b/Low Battery Yup/en.lproj/MainMenu.xib @@ -17,6 +17,7 @@ NSCustomView NSMenu NSMenuItem + NSUserDefaultsController NSView NSWindowTemplate @@ -1323,6 +1324,7 @@ {{82, 32}, {104, 18}} + _NS:9 YES @@ -1369,6 +1371,9 @@ NSFontManager + + YES + @@ -2076,6 +2081,22 @@ 545 + + + value: values.StartAtLogin + + + + + + value: values.StartAtLogin + value + values.StartAtLogin + 2 + + + 552 + @@ -3097,6 +3118,11 @@ + + 546 + + + @@ -3245,6 +3271,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3264,7 +3291,7 @@ - 545 + 552 -- cgit v1.2.3 From d530afa9d01ead88c06a7b8fcd384758332e9751 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 14:35:08 -0500 Subject: Add daemon to UI app bundle Add "Low Bettery Yup.d" to "Low Battery Yup"'s Target Dependencies and copy the "Low Bettery Yup.d.app" bundle into "Low Battery Yup"'s bundle resources. This will allow us to distribute the daemon more easily so there's only one app that users see instead of two. It also allows us to locate the app more easily since it's contained within the UI app's application bundle. --- Low Battery Yup.d.xcodeproj/project.pbxproj | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Low Battery Yup.d.xcodeproj/project.pbxproj b/Low Battery Yup.d.xcodeproj/project.pbxproj index b625f3b..da19448 100644 --- a/Low Battery Yup.d.xcodeproj/project.pbxproj +++ b/Low Battery Yup.d.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ D123F5A81DDF9D2400A27B7A /* DDHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = D123F5A71DDF9D2400A27B7A /* DDHotKeyCenter.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; D131EB381DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist in Resources */ = {isa = PBXBuildFile; fileRef = D131EB371DF1E8AB00504A74 /* com.teddywing.Low-Battery-Yup.StartAtLogin.plist */; }; + D131EB4B1DF203CD00504A74 /* Low Battery Yup.d.app in Resources */ = {isa = PBXBuildFile; fileRef = D18C949E1DDC33CF00E03F87 /* Low Battery Yup.d.app */; }; D15D90B71DF0465E001700CD /* ShortcutView.m in Sources */ = {isa = PBXBuildFile; fileRef = D15D90B61DF0465E001700CD /* ShortcutView.m */; }; D1871D071DE094AB00B8030D /* DDHotKeyTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D1871D061DE094AB00B8030D /* DDHotKeyTextField.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; D1871D081DE094C200B8030D /* DDHotKeyUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D1A37AF01DE001770022434D /* DDHotKeyUtilities.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; @@ -35,6 +36,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + D131EB451DF2034E00504A74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D18C94951DDC33CF00E03F87 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D18C949D1DDC33CF00E03F87; + remoteInfo = "Low Battery Yup.d"; + }; D195AE591DDC774300A53A18 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D195AE4F1DDC774200A53A18 /* MASShortcut.xcodeproj */; @@ -272,6 +280,7 @@ buildRules = ( ); dependencies = ( + D131EB461DF2034E00504A74 /* PBXTargetDependency */, D1D440591DDD9B50003721DE /* PBXTargetDependency */, ); name = "Low Battery Yup"; @@ -355,6 +364,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D131EB4B1DF203CD00504A74 /* Low Battery Yup.d.app in Resources */, D1F809E71DDC6AA0001671E9 /* InfoPlist.strings in Resources */, D1F809ED1DDC6AA0001671E9 /* Credits.rtf in Resources */, D1F809F31DDC6AA0001671E9 /* MainMenu.xib in Resources */, @@ -396,6 +406,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + D131EB461DF2034E00504A74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D18C949D1DDC33CF00E03F87 /* Low Battery Yup.d */; + targetProxy = D131EB451DF2034E00504A74 /* PBXContainerItemProxy */; + }; D1D440591DDD9B50003721DE /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = MASShortcut; -- cgit v1.2.3 From 7a11bfeb961f52dc9e840c1db7161ad08c436aff Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 14:38:07 -0500 Subject: Launch the daemon when "Start at login" is checked Launch the daemon when checked and quit it when unchecked. Now that I'm committing this, I don't really think this is the exact right behaviour. I think running and terminating the app should be maybe a different control so that running it isn't contingent on having it start at login. --- Low Battery Yup/AppDelegate.h | 2 ++ Low Battery Yup/AppDelegate.m | 4 ++++ Low Battery Yup/DaemonLauncher.h | 3 +++ Low Battery Yup/DaemonLauncher.m | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/Low Battery Yup/AppDelegate.h b/Low Battery Yup/AppDelegate.h index 4ae3e9c..b120b65 100644 --- a/Low Battery Yup/AppDelegate.h +++ b/Low Battery Yup/AppDelegate.h @@ -10,6 +10,7 @@ #import #import "ShortcutView.h" #import "LaunchAgentManager.h" +#import "DaemonLauncher.h" @interface AppDelegate : NSObject { IBOutlet NSWindow *window; @@ -17,6 +18,7 @@ IBOutlet NSButton *_start_at_login; LaunchAgentManager *_launchagent; + DaemonLauncher *_daemon_launcher; } - (void)initializeShortcutView; diff --git a/Low Battery Yup/AppDelegate.m b/Low Battery Yup/AppDelegate.m index 365b1bf..9cbfade 100644 --- a/Low Battery Yup/AppDelegate.m +++ b/Low Battery Yup/AppDelegate.m @@ -16,6 +16,7 @@ self = [super init]; if (self) { _launchagent = [[LaunchAgentManager alloc] init]; + _daemon_launcher = [[DaemonLauncher alloc] init]; } return self; } @@ -23,6 +24,7 @@ - (void)dealloc { [_launchagent release]; + [_daemon_launcher release]; [super dealloc]; } @@ -48,9 +50,11 @@ { if ([_start_at_login state] == NSOnState) { [_launchagent install]; + [_daemon_launcher launch]; } else { [_launchagent uninstall]; + [_daemon_launcher quit]; } } diff --git a/Low Battery Yup/DaemonLauncher.h b/Low Battery Yup/DaemonLauncher.h index a62a256..a7c6ceb 100644 --- a/Low Battery Yup/DaemonLauncher.h +++ b/Low Battery Yup/DaemonLauncher.h @@ -10,4 +10,7 @@ @interface DaemonLauncher : NSObject +- (BOOL)launch; +- (BOOL)quit; + @end diff --git a/Low Battery Yup/DaemonLauncher.m b/Low Battery Yup/DaemonLauncher.m index 4c6449c..78b7844 100644 --- a/Low Battery Yup/DaemonLauncher.m +++ b/Low Battery Yup/DaemonLauncher.m @@ -10,4 +10,36 @@ @implementation DaemonLauncher +- (BOOL)launch +{ + NSURL *daemon_url = [[NSBundle mainBundle] URLForResource:@"Low Battery Yup.d" withExtension:@"app"]; + + NSError *error = nil; + [[NSWorkspace sharedWorkspace] + launchApplicationAtURL:daemon_url + options:NSWorkspaceLaunchWithoutAddingToRecents | NSWorkspaceLaunchWithoutActivation + configuration:nil + error:&error]; + + if (error != nil) { + NSLog(@"%@", error); + return NO; + } + + return YES; +} + +- (BOOL)quit +{ + NSArray *applications = [NSRunningApplication + runningApplicationsWithBundleIdentifier:@"com.teddywing.Low-Battery-Yup-d"]; + + if ([applications count] > 0) { + NSRunningApplication *daemon = [applications objectAtIndex:0]; + return [daemon terminate]; + } + + return NO; +} + @end -- cgit v1.2.3 From ac1d82e1fff9039a5dabe1404d6f03faaad28ef5 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 16:39:21 -0500 Subject: DaemonLauncher: Add `isRunning` method Says whether or not the daemon app is currently running. --- Low Battery Yup/DaemonLauncher.h | 1 + Low Battery Yup/DaemonLauncher.m | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/Low Battery Yup/DaemonLauncher.h b/Low Battery Yup/DaemonLauncher.h index a7c6ceb..586dbda 100644 --- a/Low Battery Yup/DaemonLauncher.h +++ b/Low Battery Yup/DaemonLauncher.h @@ -12,5 +12,6 @@ - (BOOL)launch; - (BOOL)quit; +- (BOOL)isRunning; @end diff --git a/Low Battery Yup/DaemonLauncher.m b/Low Battery Yup/DaemonLauncher.m index 78b7844..355e9fd 100644 --- a/Low Battery Yup/DaemonLauncher.m +++ b/Low Battery Yup/DaemonLauncher.m @@ -42,4 +42,18 @@ return NO; } +- (BOOL)isRunning +{ + NSArray *runningApplications = [[NSWorkspace sharedWorkspace] runningApplications]; + + for (int i = 0; i < [runningApplications count]; i++) { + if ([[[runningApplications objectAtIndex:i] bundleIdentifier] + isEqualToString:@"com.teddywing.Low-Battery-Yup-d"]) { + return YES; + } + } + + return NO; +} + @end -- cgit v1.2.3 From e5debc332f2b11f4e768e0a5b0f2b8770c25523e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 16:45:45 -0500 Subject: DaemonLauncher.m: Check if daemon is running before launch or quit If the daemon is already running when `launch` is called, don't bother launching. If the daemon is not running when `quit` is called, don't bother quitting. --- Low Battery Yup/DaemonLauncher.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Low Battery Yup/DaemonLauncher.m b/Low Battery Yup/DaemonLauncher.m index 355e9fd..b96af44 100644 --- a/Low Battery Yup/DaemonLauncher.m +++ b/Low Battery Yup/DaemonLauncher.m @@ -12,6 +12,10 @@ - (BOOL)launch { + if ([self isRunning]) { + return NO; + } + NSURL *daemon_url = [[NSBundle mainBundle] URLForResource:@"Low Battery Yup.d" withExtension:@"app"]; NSError *error = nil; @@ -31,6 +35,10 @@ - (BOOL)quit { + if (![self isRunning]) { + return NO; + } + NSArray *applications = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.teddywing.Low-Battery-Yup-d"]; -- cgit v1.2.3 From 8de5b8fc6a3d32a6900b5e010cc3b173ec5ecad6 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 16:47:37 -0500 Subject: Revert "DaemonLauncher.m: Check if daemon is running before launch or quit" This reverts commit e5debc332f2b11f4e768e0a5b0f2b8770c25523e. Actually, I don't really like that. The methods should instead do first and error if it doesn't work. Why bother checking? We'll keep the `isRunning` method around though because we need it to know what the "Launch Application" button should read. --- Low Battery Yup/DaemonLauncher.m | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Low Battery Yup/DaemonLauncher.m b/Low Battery Yup/DaemonLauncher.m index b96af44..355e9fd 100644 --- a/Low Battery Yup/DaemonLauncher.m +++ b/Low Battery Yup/DaemonLauncher.m @@ -12,10 +12,6 @@ - (BOOL)launch { - if ([self isRunning]) { - return NO; - } - NSURL *daemon_url = [[NSBundle mainBundle] URLForResource:@"Low Battery Yup.d" withExtension:@"app"]; NSError *error = nil; @@ -35,10 +31,6 @@ - (BOOL)quit { - if (![self isRunning]) { - return NO; - } - NSArray *applications = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.teddywing.Low-Battery-Yup-d"]; -- cgit v1.2.3 From 0c796e9e499db506c142b6b0e3ae6ef8b20d9ec8 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 17:02:10 -0500 Subject: Add a button to launch & quit the daemon Add a new button to the UI that either launches or quits the daemon depending on whether it's currently running. The button is set as a "Toggle" type that will cycle between "Launch Application" and "Quit Application" labels when clicked. Depending on the button's state (0 or 1), it will either launch or quit the daemon. The button's initial state is set on the UI application's launch to determine how it should read & what it should do. --- Low Battery Yup/AppDelegate.h | 2 + Low Battery Yup/AppDelegate.m | 11 +++- Low Battery Yup/en.lproj/MainMenu.xib | 99 +++++++++++++++++++++++++++++------ 3 files changed, 94 insertions(+), 18 deletions(-) diff --git a/Low Battery Yup/AppDelegate.h b/Low Battery Yup/AppDelegate.h index b120b65..0504102 100644 --- a/Low Battery Yup/AppDelegate.h +++ b/Low Battery Yup/AppDelegate.h @@ -16,6 +16,7 @@ IBOutlet NSWindow *window; IBOutlet ShortcutView *_shortcut_view; IBOutlet NSButton *_start_at_login; + IBOutlet NSButton *_launch_app; LaunchAgentManager *_launchagent; DaemonLauncher *_daemon_launcher; @@ -23,5 +24,6 @@ - (void)initializeShortcutView; - (IBAction)performStartAtLogin:(id)sender; +- (IBAction)launchOrQuitDaemon:(id)sender; @end diff --git a/Low Battery Yup/AppDelegate.m b/Low Battery Yup/AppDelegate.m index 9cbfade..69081ca 100644 --- a/Low Battery Yup/AppDelegate.m +++ b/Low Battery Yup/AppDelegate.m @@ -32,6 +32,7 @@ { [self initializeShortcutView]; [self performStartAtLogin:self]; + [_launch_app setState:[_daemon_launcher isRunning]]; } - (void)initializeShortcutView @@ -50,10 +51,18 @@ { if ([_start_at_login state] == NSOnState) { [_launchagent install]; - [_daemon_launcher launch]; } else { [_launchagent uninstall]; + } +} + +- (IBAction)launchOrQuitDaemon:(id)sender +{ + if ([_launch_app state]) { + [_daemon_launcher launch]; + } + else { [_daemon_launcher quit]; } } diff --git a/Low Battery Yup/en.lproj/MainMenu.xib b/Low Battery Yup/en.lproj/MainMenu.xib index 54cde7c..f8f0d64 100644 --- a/Low Battery Yup/en.lproj/MainMenu.xib +++ b/Low Battery Yup/en.lproj/MainMenu.xib @@ -1311,7 +1311,7 @@ 268 - {{84, 83}, {313, 19}} + {{84, 100}, {313, 19}} @@ -1324,14 +1324,14 @@ {{82, 32}, {104, 18}} - + _NS:9 YES -2080374784 268435456 Start at login - + LucidaGrande 13 1044 @@ -1354,6 +1354,31 @@ NO + + + 268 + {{242, 24}, {161, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Launch Application + + _NS:9 + + -930988032 + 129 + Quit Application + + 200 + 25 + + NO + {480, 185} @@ -1371,7 +1396,7 @@ NSFontManager - + YES @@ -2081,14 +2106,30 @@ 545 + + + launchOrQuitDaemon: + + + + 555 + + + + _launch_app + + + + 556 + value: values.StartAtLogin - + - + value: values.StartAtLogin value values.StartAtLogin @@ -2622,8 +2663,9 @@ 372 - + + @@ -3120,9 +3162,22 @@ 546 - + + + 553 + + + + + + + + 554 + + + @@ -3272,6 +3327,8 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3291,25 +3348,29 @@ - 552 + 559 AppDelegate NSObject - - performStartAtLogin: - id - - - performStartAtLogin: - + + id + id + + + + launchOrQuitDaemon: + id + + performStartAtLogin: id - + + NSButton ShortcutView NSButton MASShortcutView @@ -3317,6 +3378,10 @@ NSWindow + + _launch_app + NSButton + _shortcut_view ShortcutView -- cgit v1.2.3 From 83cf716ed5534dcfc26a3e0a6e8463979989772f Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 2 Dec 2016 17:33:43 -0500 Subject: Populate launchd plist Add the necessary keys to the launchd plist to start the daemon application with the right properties on login. Used the Tunnelblick launchd plist as a reference. --- .../com.teddywing.Low-Battery-Yup.StartAtLogin.plist | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist b/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist index 0c67376..37ece9c 100644 --- a/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist +++ b/Low Battery Yup/com.teddywing.Low-Battery-Yup.StartAtLogin.plist @@ -1,5 +1,17 @@ - + + Label + com.teddywing.Low-Battery-Yup.StartAtLogin + ProgramArguments + + /usr/bin/open + /Applications/Low Battery Yup.app/Contents/Resources/Low Battery Yup.d.app + + LimitLoadToSessionType + Aqua + RunAtLoad + + -- cgit v1.2.3