Browse Source

Final changes!

v1.2.4
Abhishek Banthia 9 years ago
parent
commit
b371da40f8
  1. 16
      Clocker-Helper/Clocker-Helper.xcodeproj/project.pbxproj
  2. 38
      Clocker-Helper/Clocker-Helper/AppDelegate.m
  3. 12
      Clocker-Helper/Clocker-Helper/MainMenu.xib
  4. 39
      Clocker.xcodeproj/project.pbxproj
  5. BIN
      Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate
  6. 3
      Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  7. 104
      Clocker/ApplicationDelegate.m
  8. 13
      Clocker/CLPanelTextField.h
  9. 48
      Clocker/CLPanelTextField.m
  10. 28
      Clocker/CLPausableTimer.h
  11. 103
      Clocker/CLPausableTimer.m
  12. 4
      Clocker/Clocker-Info.plist
  13. 3
      Clocker/Custom Table Cell Views/CLTimezoneCellView.h
  14. 95
      Clocker/Custom Table Cell Views/CLTimezoneCellView.m
  15. 3
      Clocker/Floating Window/CLFloatingWindowController.h
  16. 5
      Clocker/Floating Window/CLFloatingWindowController.m
  17. 5
      Clocker/Floating Window/en.lproj/CLFloatingWindow.xib
  18. 4
      Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib
  19. 4
      Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib
  20. 3
      Clocker/Model/CLTimezoneData.m
  21. 1
      Clocker/PanelController.h
  22. 58
      Clocker/PanelController.m
  23. 11
      Clocker/Preferences/CLPreferencesViewController.m
  24. 2
      Clocker/Rate App/iRate.m
  25. 10
      README.md

16
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 = "<group>"; };
9A20A0631C4E801500FB45AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9A20A0731C4E80D300FB45AB /* Clocker-Helper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clocker-Helper.entitlements"; sourceTree = "<group>"; };
9A8597D41CDA916A00323D9D /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
/* 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 = "<group>";
@ -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";

38
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 {

12
Clocker-Helper/Clocker-Helper/MainMenu.xib

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner"/>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
</objects>
</document>

39
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 = "<group>"; };
9A10C6871CDAAB3000D474F1 /* CLPausableTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLPausableTimer.m; path = Clocker/CLPausableTimer.m; sourceTree = "<group>"; };
9A10C68D1CDAC8B500D474F1 /* CLPanelTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLPanelTextField.h; path = Clocker/CLPanelTextField.h; sourceTree = "<group>"; };
9A10C68E1CDAC8B500D474F1 /* CLPanelTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLPanelTextField.m; path = Clocker/CLPanelTextField.m; sourceTree = "<group>"; };
9A13BAC71CA86A88007C6CBE /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CLAboutUsView.xib; sourceTree = "<group>"; };
9A13BAC91CA86AAE007C6CBE /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CLAboutUsView.xib; sourceTree = "<group>"; };
9A13BACB1CA877A6007C6CBE /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CLPreferencesView.xib; sourceTree = "<group>"; };
@ -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 = "<group>";
@ -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 = (

BIN
Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate generated

Binary file not shown.

3
Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@ -13,6 +13,7 @@
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
<<<<<<< HEAD
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@ -66,5 +67,7 @@
</Locations>
</BreakpointContent>
</BreakpointProxy>
=======
>>>>>>> master
</Breakpoints>
</Bucket>

104
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

13
Clocker/CLPanelTextField.h

@ -0,0 +1,13 @@
//
// CLPanelTextField.h
// Clocker
//
// Created by Abhishek Banthia on 5/4/16.
//
//
#import <Cocoa/Cocoa.h>
@interface CLPanelTextField : NSTextField
@end

48
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

28
Clocker/CLPausableTimer.h

@ -0,0 +1,28 @@
//
// CLPausableTimer.h
// Clocker
//
// Created by Abhishek Banthia on 5/4/16.
//
//
#import <Foundation/Foundation.h>
@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

103
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

4
Clocker/Clocker-Info.plist

@ -17,7 +17,11 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<<<<<<< HEAD
<string>22</string>
=======
<string>17</string>
>>>>>>> master
<key>Fabric</key>
<dict>
<key>APIKey</key>

3
Clocker/Custom Table Cell Views/CLTimezoneCellView.h

@ -8,7 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface CLTimezoneCellView : NSTableCellView
@interface CLTimezoneCellView : NSTableCellView<NSTextDelegate>
@property (weak) IBOutlet NSTextField *customName;
@property (weak) IBOutlet NSTextField *relativeDate;
@ -19,3 +19,4 @@
- (void)setUpAutoLayoutWithCell:(CLTimezoneCellView *)cell;
@end

95
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

3
Clocker/Floating Window/CLFloatingWindowController.h

@ -8,10 +8,11 @@
#import <Cocoa/Cocoa.h>
#import "CLParentPanelController.h"
#import "CLPausableTimer.h"
@interface CLFloatingWindowController : CLParentPanelController <NSTableViewDataSource, NSWindowDelegate>
@property (strong, nonatomic) NSTimer *floatingWindowTimer;
@property (strong, nonatomic) CLPausableTimer *floatingWindowTimer;
+ (instancetype)sharedFloatingWindow;
- (void)updatePanelColor;

5
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
}
}

5
Clocker/Floating Window/en.lproj/CLFloatingWindow.xib

@ -33,7 +33,7 @@
<rect key="frame" x="0.0" y="0.0" width="282" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<rect key="frame" x="0.0" y="0.0" width="282" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="1"/>
@ -57,7 +57,7 @@
<rect key="frame" x="1" y="0.0" width="279" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z" customClass="CLPanelTextField">
<rect key="frame" x="7" y="33" width="154" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="6MO-wT-Yr5"/>
@ -70,6 +70,7 @@
</textFieldCell>
<connections>
<action selector="labelDidChange:" target="8mq-8K-c34" id="CdT-6J-5Bn"/>
<outlet property="delegate" destination="8mq-8K-c34" id="3CA-OP-j1f"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" tag="102" preferredMaxLayoutWidth="72" translatesAutoresizingMaskIntoConstraints="NO" id="wFR-Xg-kpb">

4
Clocker/Floating Window/ja.lproj/CLFloatingWindow.xib

@ -33,7 +33,7 @@
<rect key="frame" x="0.0" y="0.0" width="282" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<rect key="frame" x="0.0" y="0.0" width="282" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="1"/>
@ -57,7 +57,7 @@
<rect key="frame" x="1" y="0.0" width="279" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z" customClass="CLPanelTextField">
<rect key="frame" x="7" y="33" width="154" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="6MO-wT-Yr5"/>

4
Clocker/Floating Window/zh-Hans.lproj/CLFloatingWindow.xib

@ -33,7 +33,7 @@
<rect key="frame" x="0.0" y="0.0" width="282" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="55" viewBased="YES" id="lfp-oy-qHb">
<rect key="frame" x="0.0" y="0.0" width="282" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="1"/>
@ -57,7 +57,7 @@
<rect key="frame" x="1" y="0.0" width="279" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Zyy-Fw-K7Z" customClass="CLPanelTextField">
<rect key="frame" x="7" y="33" width="154" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="6MO-wT-Yr5"/>

3
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)
{

1
Clocker/PanelController.h

@ -57,7 +57,6 @@
@property (nonatomic, unsafe_unretained, readonly) id<PanelControllerDelegate> delegate;
@property (nonatomic, unsafe_unretained) IBOutlet BackgroundView *backgroundView;
@property (strong, nonatomic) PanelController *panelWindow;
@property (strong, nonatomic) NSTimer *floatingWindowTimer;
- (id)initWithDelegate:(id<PanelControllerDelegate>)delegate;
- (void)openPanel;

58
Clocker/PanelController.m

@ -352,4 +352,62 @@ static PanelController *sharedPanel = nil;
}
}
<<<<<<< HEAD
=======
-(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)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<NSDraggingInfo>)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

11
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<NSDraggingInfo>)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]) {

2
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];

10
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**
---

Loading…
Cancel
Save