diff --git a/Clocker-Helper/Clocker-Helper.xcodeproj/project.pbxproj b/Clocker-Helper/Clocker-Helper.xcodeproj/project.pbxproj index 3fb8e5c..86546a3 100644 --- a/Clocker-Helper/Clocker-Helper.xcodeproj/project.pbxproj +++ b/Clocker-Helper/Clocker-Helper.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 9A20A05A1C4E801500FB45AB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A20A0591C4E801500FB45AB /* AppDelegate.m */; }; 9A20A05D1C4E801500FB45AB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A20A05C1C4E801500FB45AB /* main.m */; }; 9A20A05F1C4E801500FB45AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9A20A05E1C4E801500FB45AB /* Assets.xcassets */; }; + 9A8597D51CDA916A00323D9D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A8597D41CDA916A00323D9D /* MainMenu.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -20,6 +21,7 @@ 9A20A05E1C4E801500FB45AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9A20A0631C4E801500FB45AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9A20A0731C4E80D300FB45AB /* Clocker-Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clocker-Helper.entitlements"; sourceTree = ""; }; + 9A8597D41CDA916A00323D9D /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -58,6 +60,7 @@ 9A20A05E1C4E801500FB45AB /* Assets.xcassets */, 9A20A0631C4E801500FB45AB /* Info.plist */, 9A20A05B1C4E801500FB45AB /* Supporting Files */, + 9A8597D41CDA916A00323D9D /* MainMenu.xib */, ); path = "Clocker-Helper"; sourceTree = ""; @@ -133,6 +136,7 @@ buildActionMask = 2147483647; files = ( 9A20A05F1C4E801500FB45AB /* Assets.xcassets in Resources */, + 9A8597D51CDA916A00323D9D /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -168,7 +172,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -212,7 +216,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -237,8 +241,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "Clocker-Helper/Clocker-Helper.entitlements"; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "Clocker-Helper/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; @@ -254,8 +258,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "Clocker-Helper/Clocker-Helper.entitlements"; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "Clocker-Helper/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; diff --git a/Clocker-Helper/Clocker-Helper/AppDelegate.m b/Clocker-Helper/Clocker-Helper/AppDelegate.m index c1be60e..885a0c9 100644 --- a/Clocker-Helper/Clocker-Helper/AppDelegate.m +++ b/Clocker-Helper/Clocker-Helper/AppDelegate.m @@ -19,10 +19,42 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + BOOL alreadyRunning = NO; + BOOL isActive = NO; - NSString *path = [[[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; - [[NSWorkspace sharedWorkspace] launchApplication:path]; - [NSApp terminate:nil]; + NSArray *running = [[NSWorkspace sharedWorkspace] runningApplications]; + + for (NSRunningApplication *app in running) + { + if ([[app bundleIdentifier] isEqualToString:@"com.abhishek.Clocker"]) { + alreadyRunning = YES; + isActive = [app isActive]; + break; + } + } + + if (!alreadyRunning || !isActive) + { + NSString *path = [[[[[[NSBundle mainBundle] bundlePath] + stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent] + stringByDeletingLastPathComponent]; + [[NSWorkspace sharedWorkspace] launchApplication:path]; + + } + + + [[NSDistributedNotificationCenter defaultCenter] addObserver:self + selector:@selector(killApp) + name:terminateNotification + object:mainAppBundleIdentifier]; + + /* + Let's not delete the helper app. This can help us determine whether app has launched at login or not. + + [NSApp terminate:nil];*/ + } - (void)applicationWillTerminate:(NSNotification *)aNotification { diff --git a/Clocker-Helper/Clocker-Helper/MainMenu.xib b/Clocker-Helper/Clocker-Helper/MainMenu.xib new file mode 100644 index 0000000..26c9560 --- /dev/null +++ b/Clocker-Helper/Clocker-Helper/MainMenu.xib @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Clocker.xcodeproj/project.pbxproj b/Clocker.xcodeproj/project.pbxproj index 55d2be4..e064128 100755 --- a/Clocker.xcodeproj/project.pbxproj +++ b/Clocker.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 9A10C6881CDAAB3000D474F1 /* CLPausableTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A10C6871CDAAB3000D474F1 /* CLPausableTimer.m */; }; + 9A10C68F1CDAC8B500D474F1 /* CLPanelTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A10C68E1CDAC8B500D474F1 /* CLPanelTextField.m */; }; 9A13BAC61CA86A88007C6CBE /* CLAboutUsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A13BAC81CA86A88007C6CBE /* CLAboutUsView.xib */; }; 9A13BACA1CA877A6007C6CBE /* CLPreferencesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A13BACC1CA877A6007C6CBE /* CLPreferencesView.xib */; }; 9A13BACE1CA879E5007C6CBE /* CLAppearanceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A13BAD01CA879E5007C6CBE /* CLAppearanceView.xib */; }; @@ -99,6 +101,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 9A10C6861CDAAB3000D474F1 /* CLPausableTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLPausableTimer.h; path = Clocker/CLPausableTimer.h; sourceTree = ""; }; + 9A10C6871CDAAB3000D474F1 /* CLPausableTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLPausableTimer.m; path = Clocker/CLPausableTimer.m; sourceTree = ""; }; + 9A10C68D1CDAC8B500D474F1 /* CLPanelTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLPanelTextField.h; path = Clocker/CLPanelTextField.h; sourceTree = ""; }; + 9A10C68E1CDAC8B500D474F1 /* CLPanelTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLPanelTextField.m; path = Clocker/CLPanelTextField.m; sourceTree = ""; }; 9A13BAC71CA86A88007C6CBE /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CLAboutUsView.xib; sourceTree = ""; }; 9A13BAC91CA86AAE007C6CBE /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CLAboutUsView.xib; sourceTree = ""; }; 9A13BACB1CA877A6007C6CBE /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CLPreferencesView.xib; sourceTree = ""; }; @@ -264,6 +270,10 @@ 9A6362091C432F68004AD010 /* CLAPI.m */, 9A13BAE21CA882FA007C6CBE /* InfoPlist.strings */, 9A13BAEC1CA88A76007C6CBE /* Localizable.strings */, + 9A10C6861CDAAB3000D474F1 /* CLPausableTimer.h */, + 9A10C6871CDAAB3000D474F1 /* CLPausableTimer.m */, + 9A10C68D1CDAC8B500D474F1 /* CLPanelTextField.h */, + 9A10C68E1CDAC8B500D474F1 /* CLPanelTextField.m */, ); name = Utilties; sourceTree = ""; @@ -655,9 +665,11 @@ 9A8605BB1BEC14DC00A810A4 /* PanelController.m in Sources */, 9A8605B61BEC14BE00A810A4 /* MenubarController.m in Sources */, 9A42394F1CB0616400A8E51A /* CLFloatingWindowController.m in Sources */, + 9A10C68F1CDAC8B500D474F1 /* CLPanelTextField.m in Sources */, 9A5951C01C1D0AA0009C17AA /* CLOneWindowController.m in Sources */, 9A20A07E1C4EAAEB00FB45AB /* CLIntroViewController.m in Sources */, 9A8605B71BEC14BE00A810A4 /* ApplicationDelegate.m in Sources */, + 9A10C6881CDAAB3000D474F1 /* CLPausableTimer.m in Sources */, 9A5951F51C1D3D81009C17AA /* CLTimezoneCellView.m in Sources */, 9ABF58721C29A80600BD0187 /* CLTimezoneData.m in Sources */, 9A8605AE1BEC148400A810A4 /* main.m in Sources */, @@ -794,7 +806,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Abhishek Banthia (AJS5SNW8EY)"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -821,8 +833,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; +<<<<<<< HEAD + "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; +======= +>>>>>>> master COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -855,7 +870,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Abhishek Banthia (AJS5SNW8EY)"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -895,7 +910,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Abhishek Banthia (AJS5SNW8EY)"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -922,8 +937,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; +<<<<<<< HEAD + "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; +======= +>>>>>>> master COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -953,8 +971,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = Clocker/Clocker.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer: Abhishek Banthia (75WFZYE9LW)"; + CODE_SIGN_IDENTITY = ""; +<<<<<<< HEAD + "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; +======= +>>>>>>> master COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate b/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate index a362412..d8612ee 100644 Binary files a/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate and b/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index f28871b..508ac5c 100644 --- a/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -13,6 +13,7 @@ stopOnStyle = "0"> +<<<<<<< HEAD +======= +>>>>>>> master diff --git a/Clocker/ApplicationDelegate.m b/Clocker/ApplicationDelegate.m index cd2c9be..aad6fb8 100755 --- a/Clocker/ApplicationDelegate.m +++ b/Clocker/ApplicationDelegate.m @@ -34,7 +34,7 @@ #import "CLOnboardingWindowController.h" #define helperAppBundleIdentifier @"com.abhishek.Clocker-Helper" // change as appropriate to help app bundle identifier -#define terminateNotification @"TerminateHelper" +#define terminateNotification @"TERMINATEHELPER" // can be basically any string @implementation ApplicationDelegate @@ -76,29 +76,96 @@ void *kContextActivePanel = &kContextActivePanel; - (void)applicationDidFinishLaunching:(NSNotification *)notification { +<<<<<<< HEAD + BOOL startedAtLogin = NO; +======= + NSNumber *opened = [[NSUserDefaults standardUserDefaults] objectForKey:@"noOfTimes"]; + if (opened == nil) + { + [[NSUserDefaults standardUserDefaults] setObject:[NSMutableArray array] + forKey:CLDefaultPreferenceKey]; + NSInteger noOfTimes = opened.integerValue + 1; + NSNumber *noOfTime = [NSNumber numberWithInteger:noOfTimes]; + [[NSUserDefaults standardUserDefaults] setObject:noOfTime forKey:@"noOfTimes"];; + + } + + + NSArray *defaultPreference = [[NSUserDefaults standardUserDefaults] objectForKey:CLDefaultPreferenceKey]; +>>>>>>> master + + NSArray *apps = [[NSWorkspace sharedWorkspace] runningApplications]; + + for (NSRunningApplication *app in apps) + { + if ([app.bundleIdentifier isEqualToString:helperAppBundleIdentifier]) + { + startedAtLogin = YES; + break; + } + } + + + if (startedAtLogin) + { + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName:terminateNotification + object:[[NSBundle mainBundle] bundleIdentifier]]; + } + + // Install icon into the menu bar + self.menubarController = [MenubarController new]; + + [self initializeDefaults]; + + NSString *onboarding = [[NSUserDefaults standardUserDefaults] objectForKey:@"initialLaunch"]; + + if (onboarding == nil) + { + CLOnboardingWindowController *windowController = [CLOnboardingWindowController sharedWindow]; + [windowController showWindow:nil]; + [NSApp activateIgnoringOtherApps:YES]; + [[NSUserDefaults standardUserDefaults] setObject:@"OnboardingDone" forKey:@"initialLaunch"]; + [self.menubarController setInitialTimezoneData]; + } + + [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions": @YES }]; + + [[Crashlytics sharedInstance] setDebugMode:NO]; + [Fabric with:@[[Crashlytics class]]]; + +} + +- (void)initializeDefaults +{ NSString *defaultTheme = [[NSUserDefaults standardUserDefaults] objectForKey:CLThemeKey]; - if (defaultTheme == nil) { + if (defaultTheme == nil) + { [[NSUserDefaults standardUserDefaults] setObject:@0 forKey:CLThemeKey]; } NSNumber *displayFutureSlider = [[NSUserDefaults standardUserDefaults] objectForKey:CLDisplayFutureSliderKey]; - if (displayFutureSlider == nil) { + if (displayFutureSlider == nil) + { [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:0] forKey:CLDisplayFutureSliderKey]; } NSNumber *defaultTimeFormat = [[NSUserDefaults standardUserDefaults] objectForKey:CL24hourFormatSelectedKey]; - if (defaultTimeFormat == nil) { + if (defaultTimeFormat == nil) + { [[NSUserDefaults standardUserDefaults] setObject:@1 forKey:CL24hourFormatSelectedKey]; } NSNumber *relativeDate = [[NSUserDefaults standardUserDefaults] objectForKey:CLRelativeDateKey]; - if (relativeDate == nil) { + if (relativeDate == nil) + { [[NSUserDefaults standardUserDefaults] setObject:@0 forKey:CLRelativeDateKey]; } NSNumber *showDayInMenuBar = [[NSUserDefaults standardUserDefaults] objectForKey:CLShowDayInMenu]; - if (showDayInMenuBar == nil) { + if (showDayInMenuBar == nil) + { [[NSUserDefaults standardUserDefaults] setObject:@0 forKey:CLShowDayInMenu]; } @@ -108,7 +175,8 @@ void *kContextActivePanel = &kContextActivePanel; } NSNumber *showCityInMenu = [[NSUserDefaults standardUserDefaults] objectForKey:CLShowPlaceInMenu]; - if (showCityInMenu == nil) { + if (showCityInMenu == nil) + { [[NSUserDefaults standardUserDefaults] setObject:@0 forKey:CLShowPlaceInMenu]; } @@ -127,20 +195,6 @@ void *kContextActivePanel = &kContextActivePanel; [[NSUserDefaults standardUserDefaults] setObject:@0 forKey:CLShowAppInForeground]; } - NSString *onboarding = [[NSUserDefaults standardUserDefaults] objectForKey:@"initialLaunch"]; - - // Install icon into the menu bar - self.menubarController = [MenubarController new]; - - if (onboarding == nil) - { - CLOnboardingWindowController *windowController = [CLOnboardingWindowController sharedWindow]; - [windowController showWindow:nil]; - [NSApp activateIgnoringOtherApps:YES]; - [[NSUserDefaults standardUserDefaults] setObject:@"OnboardingDone" forKey:@"initialLaunch"]; - [self.menubarController setInitialTimezoneData]; - } - //If mode selected is 1, then show the window when the app starts if (displayMode.integerValue == 1) { @@ -152,15 +206,9 @@ void *kContextActivePanel = &kContextActivePanel; [NSApp activateIgnoringOtherApps:YES]; } - - [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions": @YES }]; - - [[Crashlytics sharedInstance] setDebugMode:NO]; - [Fabric with:@[[Crashlytics class]]]; - -} +} - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender diff --git a/Clocker/CLPanelTextField.h b/Clocker/CLPanelTextField.h new file mode 100644 index 0000000..21ab013 --- /dev/null +++ b/Clocker/CLPanelTextField.h @@ -0,0 +1,13 @@ +// +// CLPanelTextField.h +// Clocker +// +// Created by Abhishek Banthia on 5/4/16. +// +// + +#import + +@interface CLPanelTextField : NSTextField + +@end diff --git a/Clocker/CLPanelTextField.m b/Clocker/CLPanelTextField.m new file mode 100644 index 0000000..e844afa --- /dev/null +++ b/Clocker/CLPanelTextField.m @@ -0,0 +1,48 @@ +// +// CLPanelTextField.m +// Clocker +// +// Created by Abhishek Banthia on 5/4/16. +// +// + +#import "CLPanelTextField.h" +#import "CLFloatingWindowController.h" + +@implementation CLPanelTextField + +- (void)drawRect:(NSRect)dirtyRect { + [super drawRect:dirtyRect]; + + // Drawing code here. +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + [super mouseDown:theEvent]; + + CLFloatingWindowController *windowController = [CLFloatingWindowController sharedFloatingWindow]; + + [windowController.floatingWindowTimer pause]; +} + +- (void)mouseUp:(NSEvent *)theEvent +{ + [super mouseUp:theEvent]; + + CLFloatingWindowController *windowController = [CLFloatingWindowController sharedFloatingWindow]; + + [windowController.floatingWindowTimer pause]; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent +{ + return YES; +} + +@end diff --git a/Clocker/CLPausableTimer.h b/Clocker/CLPausableTimer.h new file mode 100644 index 0000000..6e1ceb4 --- /dev/null +++ b/Clocker/CLPausableTimer.h @@ -0,0 +1,28 @@ +// +// CLPausableTimer.h +// Clocker +// +// Created by Abhishek Banthia on 5/4/16. +// +// + +#import + +@interface CLPausableTimer : NSObject + +//Timer Info +@property (nonatomic) NSTimeInterval timeInterval; +@property (nonatomic, weak) id target; +@property (nonatomic) SEL selector; +@property (nonatomic) id userInfo; +@property (nonatomic) BOOL repeats; + +@property (strong, nonatomic) NSTimer *timer; +@property (nonatomic) BOOL isPaused; + ++(CLPausableTimer *)timerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)selector userInfo:(id)userInfo repeats:(BOOL)repeats; + +-(void)pause; +-(void)start; + +@end diff --git a/Clocker/CLPausableTimer.m b/Clocker/CLPausableTimer.m new file mode 100644 index 0000000..a42c6f7 --- /dev/null +++ b/Clocker/CLPausableTimer.m @@ -0,0 +1,103 @@ +// +// CLPausableTimer.m +// Clocker +// +// Created by Abhishek Banthia on 5/4/16. +// +// + +#import "CLPausableTimer.h" + +@implementation CLPausableTimer + +{ + NSDate *cycleStartDate; + NSTimeInterval remainingInterval; + BOOL hasPausedThisCycle; +} + ++(CLPausableTimer *)timerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)selector userInfo:(id)userInfo repeats:(BOOL)repeats +{ + + CLPausableTimer *new = [[CLPausableTimer alloc] init]; + new.timeInterval = timeInterval; + new.target = target; + new.selector = selector; + new.userInfo = userInfo; + new.repeats = repeats; + + return new; +} + +-(void)start +{ + + [self.timer invalidate]; + + if(self.isPaused) + { //If resuming from a pause, use partial remaining time interval + self.timer = [NSTimer scheduledTimerWithTimeInterval:remainingInterval target:self selector:@selector(timerFired:) userInfo:self.userInfo repeats:self.repeats]; + + } else { + self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeInterval target:self selector:@selector(timerFired:) userInfo:self.userInfo repeats:self.repeats]; + + remainingInterval = self.timeInterval; + } + + self.isPaused = NO; + cycleStartDate = [NSDate date]; + +} + +-(void)pause +{ + if(self.isPaused) return; + + self.isPaused = YES; + hasPausedThisCycle = YES; + + [self.timer invalidate]; + + //keep track of time left on this cycle + remainingInterval -= [[NSDate date] timeIntervalSinceDate:cycleStartDate]; +} + +-(void)timerFired:(NSTimer *)timer +{ + if(self.isPaused) return; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [self.target performSelector:self.selector withObject:self]; +#pragma clang diagnostic pop + + //reset remaining time to original value + remainingInterval = self.timeInterval; + cycleStartDate = [NSDate date]; + + if(hasPausedThisCycle) + { + //current timer is running on remainingInterval + + //reset pause flag for next cycle + hasPausedThisCycle = NO; + + if(self.repeats) + { //need to set up a new timer with original timeInterval + [self.timer invalidate]; + [self start]; + } + + } +} + +-(void)dealloc +{ + [self.timer invalidate]; + self.timer = nil; + self.selector = nil; + self.target = nil; + self.userInfo = nil; +} + +@end diff --git a/Clocker/Clocker-Info.plist b/Clocker/Clocker-Info.plist index 5f6b4a6..6cd12d9 100755 --- a/Clocker/Clocker-Info.plist +++ b/Clocker/Clocker-Info.plist @@ -17,7 +17,11 @@ CFBundleSignature ???? CFBundleVersion +<<<<<<< HEAD 22 +======= + 17 +>>>>>>> master Fabric APIKey diff --git a/Clocker/Custom Table Cell Views/CLTimezoneCellView.h b/Clocker/Custom Table Cell Views/CLTimezoneCellView.h index 71255a9..0dc119e 100644 --- a/Clocker/Custom Table Cell Views/CLTimezoneCellView.h +++ b/Clocker/Custom Table Cell Views/CLTimezoneCellView.h @@ -8,7 +8,7 @@ #import -@interface CLTimezoneCellView : NSTableCellView +@interface CLTimezoneCellView : NSTableCellView @property (weak) IBOutlet NSTextField *customName; @property (weak) IBOutlet NSTextField *relativeDate; @@ -19,3 +19,4 @@ - (void)setUpAutoLayoutWithCell:(CLTimezoneCellView *)cell; @end + diff --git a/Clocker/Custom Table Cell Views/CLTimezoneCellView.m b/Clocker/Custom Table Cell Views/CLTimezoneCellView.m index 1af2202..55cab63 100644 --- a/Clocker/Custom Table Cell Views/CLTimezoneCellView.m +++ b/Clocker/Custom Table Cell Views/CLTimezoneCellView.m @@ -10,25 +10,43 @@ #import "PanelController.h" #import "CommonStrings.h" #import "CLTimezoneData.h" +#import "CLFloatingWindowController.h" @implementation CLTimezoneCellView - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; - + // Drawing code here. } -- (IBAction)labelDidChange:(id)sender +- (IBAction)labelDidChange:(NSTextField *)sender { NSTextField *customLabelCell = (NSTextField*) sender; __block PanelController *panelController; + __block CLFloatingWindowController *floatingWindow; + + NSNumber *displayMode = [[NSUserDefaults standardUserDefaults] objectForKey:CLShowAppInForeground]; + - [[[NSApplication sharedApplication] windows] enumerateObjectsUsingBlock:^(NSWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { - if ([window.windowController isMemberOfClass:[PanelController class]]) + [[[NSApplication sharedApplication] windows] enumerateObjectsUsingBlock:^(NSWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) + { + if (displayMode.integerValue == 0) + { + if ([window.windowController isMemberOfClass:[PanelController class]]) + { + panelController = window.windowController; + } + } + else if (displayMode.integerValue == 1) { - panelController = window.windowController; + if ([window.windowController isMemberOfClass:[CLFloatingWindowController class]]) + { + floatingWindow = window.windowController; + } } + + }]; NSString *originalValue = customLabelCell.stringValue; @@ -36,20 +54,34 @@ [NSCharacterSet whitespaceCharacterSet]]; - if ([[sender superview] isKindOfClass:[self class]]) { + if ([[sender superview] isKindOfClass:[self class]]) + { CLTimezoneCellView *cellView = (CLTimezoneCellView *)[sender superview]; - NSData *dataObject = panelController.defaultPreferences[cellView.rowNumber]; + NSData *dataObject = displayMode.integerValue == 0 ? panelController.defaultPreferences[cellView.rowNumber] : floatingWindow.defaultPreferences[cellView.rowNumber]; CLTimezoneData *timezoneObject = [CLTimezoneData getCustomObject:dataObject]; - [panelController.defaultPreferences enumerateObjectsUsingBlock:^(id _Nonnull object, NSUInteger idx, BOOL * _Nonnull stop) { - - CLTimezoneData *timeObject = [CLTimezoneData getCustomObject:object]; - if ([timeObject.formattedAddress isEqualToString:customLabelValue]) { - timeObject.customLabel = CLEmptyString; - } - + if (displayMode.integerValue == 0) + { - }]; + [panelController.defaultPreferences enumerateObjectsUsingBlock:^(id _Nonnull object, NSUInteger idx, BOOL * _Nonnull stop) { + + CLTimezoneData *timeObject = [CLTimezoneData getCustomObject:object]; + if ([timeObject.formattedAddress isEqualToString:customLabelValue]) { + timeObject.customLabel = CLEmptyString; + } + }]; + } + else if (displayMode.integerValue == 1) + { + [floatingWindow.defaultPreferences enumerateObjectsUsingBlock:^(id _Nonnull object, NSUInteger idx, BOOL * _Nonnull stop) { + + CLTimezoneData *timeObject = [CLTimezoneData getCustomObject:object]; + if ([timeObject.formattedAddress isEqualToString:customLabelValue]) { + timeObject.customLabel = CLEmptyString; + } + }]; + } + timezoneObject.customLabel = (customLabelValue.length > 0) ? customLabelValue : CLEmptyString; @@ -61,11 +93,21 @@ } NSData *newObject = [NSKeyedArchiver archivedDataWithRootObject:timezoneObject]; - [panelController.defaultPreferences replaceObjectAtIndex:cellView.rowNumber withObject:newObject]; - [[NSUserDefaults standardUserDefaults] setObject:panelController.defaultPreferences forKey:CLDefaultPreferenceKey]; - [panelController updateDefaultPreferences]; - [panelController.mainTableview reloadData]; + if (displayMode.integerValue == 0) + { + [panelController.defaultPreferences replaceObjectAtIndex:cellView.rowNumber withObject:newObject]; + [[NSUserDefaults standardUserDefaults] setObject:panelController.defaultPreferences forKey:CLDefaultPreferenceKey]; + [panelController updateDefaultPreferences]; + [panelController.mainTableview reloadData]; + } + else if(displayMode.integerValue == 1) + { + [floatingWindow.defaultPreferences replaceObjectAtIndex:cellView.rowNumber withObject:newObject]; + [[NSUserDefaults standardUserDefaults] setObject:floatingWindow.defaultPreferences forKey:CLDefaultPreferenceKey]; + [floatingWindow updateDefaultPreferences]; + [floatingWindow.mainTableview reloadData]; + } [[NSNotificationCenter defaultCenter] postNotificationName:CLCustomLabelChangedNotification @@ -74,6 +116,11 @@ } } +-(void)mouseDown:(NSEvent *)theEvent +{ + [self.window endEditingFor:nil]; +} + - (void)updateTextColorWithColor:(NSColor *)color andCell:(CLTimezoneCellView*)cell { cell.relativeDate.textColor = color; @@ -97,4 +144,12 @@ }]; } -@end +- (void)controlTextDidEndEditing:(NSNotification *)obj +{ + + CLFloatingWindowController *windowController = [CLFloatingWindowController sharedFloatingWindow]; + + [windowController.floatingWindowTimer start]; +} + +@end \ No newline at end of file diff --git a/Clocker/Floating Window/CLFloatingWindowController.h b/Clocker/Floating Window/CLFloatingWindowController.h index 5c106d8..e887979 100644 --- a/Clocker/Floating Window/CLFloatingWindowController.h +++ b/Clocker/Floating Window/CLFloatingWindowController.h @@ -8,10 +8,11 @@ #import #import "CLParentPanelController.h" +#import "CLPausableTimer.h" @interface CLFloatingWindowController : CLParentPanelController -@property (strong, nonatomic) NSTimer *floatingWindowTimer; +@property (strong, nonatomic) CLPausableTimer *floatingWindowTimer; + (instancetype)sharedFloatingWindow; - (void)updatePanelColor; diff --git a/Clocker/Floating Window/CLFloatingWindowController.m b/Clocker/Floating Window/CLFloatingWindowController.m index 9928b54..fd2807e 100644 --- a/Clocker/Floating Window/CLFloatingWindowController.m +++ b/Clocker/Floating Window/CLFloatingWindowController.m @@ -306,7 +306,7 @@ NSString *const CLTimezoneCellIdentifier = @"timeZoneCell"; if (self.floatingWindowTimer) { - [self.floatingWindowTimer invalidate]; + [self.floatingWindowTimer.timer invalidate]; self.floatingWindowTimer = nil; } } @@ -315,10 +315,11 @@ NSString *const CLTimezoneCellIdentifier = @"timeZoneCell"; { if (!self.floatingWindowTimer) { - self.floatingWindowTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 + self.floatingWindowTimer = [CLPausableTimer timerWithTimeInterval:2.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES]; + [self.floatingWindowTimer start]; //Explicitly start the timer } } diff --git a/Clocker/Floating Window/en.lproj/CLFloatingWindow.xib b/Clocker/Floating Window/en.lproj/CLFloatingWindow.xib index f31bfbc..6385dca 100644 --- a/Clocker/Floating Window/en.lproj/CLFloatingWindow.xib +++ b/Clocker/Floating Window/en.lproj/CLFloatingWindow.xib @@ -33,7 +33,7 @@ - + @@ -57,7 +57,7 @@ - + @@ -70,6 +70,7 @@ + diff --git a/Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib b/Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib index 404d525..7075590 100644 --- a/Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib +++ b/Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib @@ -33,7 +33,7 @@ - + @@ -57,7 +57,7 @@ - + diff --git a/Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib b/Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib index cc999ef..2d1ed7d 100644 --- a/Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib +++ b/Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib @@ -33,7 +33,7 @@ - + @@ -57,7 +57,7 @@ - + diff --git a/Clocker/Model/CLTimezoneData.m b/Clocker/Model/CLTimezoneData.m index ac2c17b..ad57d27 100644 --- a/Clocker/Model/CLTimezoneData.m +++ b/Clocker/Model/CLTimezoneData.m @@ -416,9 +416,6 @@ - (void)sendAnalyticsData { - NSAssert(self.formattedAddress != nil, @"Formatted Address cannot be nil before sending analytics"); - NSAssert(self.timezoneID != nil, @"Timezone ID cannot be nil before sending analytics"); - NSString *uniqueIdentifier = [self getSerialNumber]; if (uniqueIdentifier == nil) { diff --git a/Clocker/PanelController.h b/Clocker/PanelController.h index 24d185d..cc642d1 100755 --- a/Clocker/PanelController.h +++ b/Clocker/PanelController.h @@ -57,7 +57,6 @@ @property (nonatomic, unsafe_unretained, readonly) id delegate; @property (nonatomic, unsafe_unretained) IBOutlet BackgroundView *backgroundView; @property (strong, nonatomic) PanelController *panelWindow; -@property (strong, nonatomic) NSTimer *floatingWindowTimer; - (id)initWithDelegate:(id)delegate; - (void)openPanel; diff --git a/Clocker/PanelController.m b/Clocker/PanelController.m index 5b191b6..94e56a2 100755 --- a/Clocker/PanelController.m +++ b/Clocker/PanelController.m @@ -352,4 +352,62 @@ static PanelController *sharedPanel = nil; } } +<<<<<<< HEAD +======= + +-(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation +{ + if (row == self.defaultPreferences.count) { + row--; + } + + NSPasteboard *pBoard = [info draggingPasteboard]; + + NSData *data = [pBoard dataForType:CLDragSessionKey]; + + NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + + [self.defaultPreferences exchangeObjectAtIndex:rowIndexes.firstIndex withObjectAtIndex:row]; + + [[NSUserDefaults standardUserDefaults] setObject:self.defaultPreferences forKey:CLDefaultPreferenceKey]; + + [self.mainTableview reloadData]; + + return YES; +} + +-(NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation +{ + return NSDragOperationEvery; +} + +#pragma mark - +#pragma mark Preferences Target-Action +#pragma mark - + +- (IBAction)openPreferences:(id)sender +{ + self.oneWindow = [CLOneWindowController sharedWindow]; + [self.oneWindow showWindow:nil]; + [NSApp activateIgnoringOtherApps:YES]; + +} + +#pragma mark - +#pragma mark Hiding Buttons on Mouse Exit +#pragma mark - + +- (void)showOptions:(BOOL)value +{ + if (self.defaultPreferences.count == 0) + { + value = YES; + } + + self.shutdownButton.hidden = !value; + self.preferencesButton.hidden = !value; + +} + +>>>>>>> master @end diff --git a/Clocker/Preferences/CLPreferencesViewController.m b/Clocker/Preferences/CLPreferencesViewController.m index 23918f8..6873c6e 100644 --- a/Clocker/Preferences/CLPreferencesViewController.m +++ b/Clocker/Preferences/CLPreferencesViewController.m @@ -232,6 +232,7 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; else { NSMutableArray *newArray = [NSMutableArray new]; + NSNumber *isFavouriteValue = (NSNumber *)object; [self.selectedTimeZones enumerateObjectsUsingBlock:^(NSData * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { @@ -243,7 +244,7 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; }]; CLTimezoneData *dataObject = [CLTimezoneData getCustomObject:newArray[row]]; - dataObject.isFavourite = object; + dataObject.isFavourite = isFavouriteValue; NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:dataObject]; [newArray replaceObjectAtIndex:row withObject:encodedObject]; [[NSUserDefaults standardUserDefaults] setObject:newArray forKey:CLDefaultPreferenceKey]; @@ -549,7 +550,6 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; } } - }); } @@ -569,7 +569,8 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; -(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation { - if (row == self.selectedTimeZones.count) { + if (row == self.selectedTimeZones.count) + { row--; } @@ -602,7 +603,8 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; - (void)callGoogleAPiWithSearchString:(NSString *)searchString { - if (self.dataTask.state == NSURLSessionTaskStateRunning) { + if (self.dataTask.state == NSURLSessionTaskStateRunning) + { [self.dataTask cancel]; } @@ -615,7 +617,6 @@ NSString *const CLTryAgainMessage = @"Try again, maybe?"; self.availableTimezoneTableView.hidden = NO; } - self.placeholderLabel.hidden = NO; if (![CLAPI isUserConnectedToInternet]) { diff --git a/Clocker/Rate App/iRate.m b/Clocker/Rate App/iRate.m index e95834c..2ddfa98 100755 --- a/Clocker/Rate App/iRate.m +++ b/Clocker/Rate App/iRate.m @@ -941,7 +941,7 @@ static NSString *const iRateMacAppStoreURLFormat = @"macappstore://itunes.apple. for (NSWindow *window in currentWindows) { - if ([window.windowController isKindOfClass:[PanelController class]]) + if ([window.windowController isMemberOfClass:[PanelController class]]) { PanelController *panelRef = (PanelController *)[[[NSApplication sharedApplication] mainWindow] windowController]; diff --git a/README.md b/README.md index c752fbb..a5f063d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ **Clocker** --- -![Clocker](https://raw.githubusercontent.com/Abhishaker17/Clocker/master/Icons/ClockerIcon-64.png) +![Clocker](https://raw.githubusercontent.com/Abhishaker17/Clocker/v1.2.1/GitHub.png "Clocker") **Clocker** is an OSX menubar utility designed to help you keep track of your friends in different time zones. It's written using Objective-C and is completely ad-free. -You can find the latest App Store version [here](https://itunes.apple.com/us/app/clocker-menubar-world-clock/id1056643111?mt=12). Need any help? Tweet [me](https://twitter.com/Abhi_Shaker)! +[![Download on the App Store](https://github.com/Abhishaker17/Clocker/blob/v1.2.1/Clocker/Images/MacAppStore.png)](https://itunes.apple.com/us/app/clocker-menubar-world-clock/id1056643111?mt=12) -You can find a review of the app by SoftPedia [here](http://mac.softpedia.com/get/Utilities/Clocker-Banthia.shtml) - -## In Action +Need any help? Tweet [me](https://twitter.com/Abhi_Shaker)! -![Sample Animations](https://github.com/Abhishaker17/Clocker/blob/Localization/Clocker-Preview.gif) +You can find a review of the app by SoftPedia [here](http://mac.softpedia.com/get/Utilities/Clocker-Banthia.shtml) **Features** ---