Browse Source

Reachability + API additions.

v1.2.1
Abhishek Banthia 9 years ago
parent
commit
acd6c0f1e8
  1. 65
      Clocker.xcodeproj/project.pbxproj
  2. BIN
      Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/UserInterfaceState.xcuserstate
  3. 28
      Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  4. 2
      Clocker/AboutUsWindow/CLAboutUsView.xib
  5. 13
      Clocker/ApplicationDelegate.m
  6. 5
      Clocker/Clocker-Info.plist
  7. 49
      Clocker/PanelController.m
  8. 104
      Clocker/Preferences/CLPreferencesView.xib
  9. 5
      Clocker/Preferences/CLPreferencesViewController.h
  10. 445
      Clocker/Preferences/CLPreferencesViewController.m
  11. 61
      Clocker/Reachability/Reachability.h
  12. 269
      Clocker/Reachability/Reachability.m
  13. 1
      Clocker/Utilities/CommonStrings.h
  14. 3
      Clocker/Utilities/CommonStrings.m

65
Clocker.xcodeproj/project.pbxproj

@ -44,26 +44,10 @@
9A9E876F1C1FEE1A00A7A2DF /* Parse.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9A9E87581C1FED1A00A7A2DF /* Parse.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9AB9357B1C1AD8F7001285A0 /* CLRatingCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB9357A1C1AD8F7001285A0 /* CLRatingCellView.m */; };
9AC678E41C1ABAB9003B4F6B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AC678E31C1ABAB9003B4F6B /* QuartzCore.framework */; };
9AF9A16B1C250AB300EE7C2A /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AF9A16A1C250AB300EE7C2A /* Reachability.m */; };
DD4F7C0913C30F9F00825C6E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4F7C0813C30F9F00825C6E /* Cocoa.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
9A5951CC1C1D1B6F009C17AA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9A5951C71C1D1B6F009C17AA /* ApptentiveConnect.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
remoteInfo = ApptentiveConnect;
};
9A5951CE1C1D1B6F009C17AA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9A5951C71C1D1B6F009C17AA /* ApptentiveConnect.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 49626B6D13942A2B0093534C;
remoteInfo = ApptentiveUnitTests;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9A9E876D1C1FEE0B00A7A2DF /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
@ -100,7 +84,6 @@
9A5951BE1C1D0AA0009C17AA /* CLOneWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLOneWindowController.m; path = Clocker/CLOneWindow/CLOneWindowController.m; sourceTree = "<group>"; };
9A5951BF1C1D0AA0009C17AA /* CLOneWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLOneWindowController.h; path = Clocker/CLOneWindow/CLOneWindowController.h; sourceTree = "<group>"; };
9A5951C11C1D0AAD009C17AA /* CLOneWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CLOneWindow.xib; path = Clocker/CLOneWindow/CLOneWindow.xib; sourceTree = "<group>"; };
9A5951C71C1D1B6F009C17AA /* ApptentiveConnect.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ApptentiveConnect.xcodeproj; path = Clocker/ApptentiveConnect/ApptentiveConnect.xcodeproj; sourceTree = "<group>"; };
9A5951D11C1D1D94009C17AA /* ApptentiveConnect.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApptentiveConnect.framework; path = Clocker/ApptentiveConnect/ApptentiveConnect.framework; sourceTree = "<group>"; };
9A5951F31C1D3D81009C17AA /* CLTimezoneCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLTimezoneCellView.h; path = "Clocker/Custom Table Cell Views/CLTimezoneCellView.h"; sourceTree = "<group>"; };
9A5951F41C1D3D81009C17AA /* CLTimezoneCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLTimezoneCellView.m; path = "Clocker/Custom Table Cell Views/CLTimezoneCellView.m"; sourceTree = "<group>"; };
@ -136,6 +119,8 @@
9AB935791C1AD8F7001285A0 /* CLRatingCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLRatingCellView.h; path = Clocker/CLRatingCellView.h; sourceTree = "<group>"; };
9AB9357A1C1AD8F7001285A0 /* CLRatingCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLRatingCellView.m; path = Clocker/CLRatingCellView.m; sourceTree = "<group>"; };
9AC678E31C1ABAB9003B4F6B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
9AF9A1691C250AB300EE7C2A /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Reachability.h; path = Clocker/Reachability/Reachability.h; sourceTree = "<group>"; };
9AF9A16A1C250AB300EE7C2A /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Reachability.m; path = Clocker/Reachability/Reachability.m; sourceTree = "<group>"; };
DD4F7C0413C30F9F00825C6E /* Clocker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Clocker.app; sourceTree = BUILT_PRODUCTS_DIR; };
DD4F7C0813C30F9F00825C6E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
DD4F7C0B13C30F9F00825C6E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@ -194,15 +179,6 @@
name = "View Controllers";
sourceTree = "<group>";
};
9A5951C81C1D1B6F009C17AA /* Products */ = {
isa = PBXGroup;
children = (
9A5951CD1C1D1B6F009C17AA /* ApptentiveConnect.framework */,
9A5951CF1C1D1B6F009C17AA /* ApptentiveUnitTests.octest */,
);
name = Products;
sourceTree = "<group>";
};
9A5951F01C1D3D35009C17AA /* Table Cell Views */ = {
isa = PBXGroup;
children = (
@ -292,9 +268,19 @@
name = Parse;
sourceTree = "<group>";
};
9AF9A1681C250AA300EE7C2A /* Reachability */ = {
isa = PBXGroup;
children = (
9AF9A1691C250AB300EE7C2A /* Reachability.h */,
9AF9A16A1C250AB300EE7C2A /* Reachability.m */,
);
name = Reachability;
sourceTree = "<group>";
};
DD4F7BF913C30F9F00825C6E = {
isa = PBXGroup;
children = (
9AF9A1681C250AA300EE7C2A /* Reachability */,
9A9E875B1C1FED1E00A7A2DF /* Parse */,
9A5B1A8D1BECDFB700A77C68 /* Clocker.entitlements */,
9A43792D1BEC256200F4E27F /* Media.xcassets */,
@ -331,7 +317,6 @@
9A9E87631C1FEDBD00A7A2DF /* CoreGraphics.framework */,
9A9E87611C1FEDB500A7A2DF /* CFNetwork.framework */,
9A5951D11C1D1D94009C17AA /* ApptentiveConnect.framework */,
9A5951C71C1D1B6F009C17AA /* ApptentiveConnect.xcodeproj */,
9A5951B91C1D0A22009C17AA /* Crashlytics.framework */,
9AC678E31C1ABAB9003B4F6B /* QuartzCore.framework */,
9A4379211BEC223900F4E27F /* Security.framework */,
@ -395,12 +380,6 @@
mainGroup = DD4F7BF913C30F9F00825C6E;
productRefGroup = DD4F7C0513C30F9F00825C6E /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 9A5951C81C1D1B6F009C17AA /* Products */;
ProjectRef = 9A5951C71C1D1B6F009C17AA /* ApptentiveConnect.xcodeproj */;
},
);
projectRoot = "";
targets = (
DD4F7C0313C30F9F00825C6E /* Clocker */,
@ -408,23 +387,6 @@
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
9A5951CD1C1D1B6F009C17AA /* ApptentiveConnect.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = ApptentiveConnect.framework;
remoteRef = 9A5951CC1C1D1B6F009C17AA /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9A5951CF1C1D1B6F009C17AA /* ApptentiveUnitTests.octest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = ApptentiveUnitTests.octest;
remoteRef = 9A5951CE1C1D1B6F009C17AA /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
DD4F7C0213C30F9F00825C6E /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -480,6 +442,7 @@
9A8605B31BEC14A600A810A4 /* ColoredButton.m in Sources */,
9A8605AE1BEC148400A810A4 /* main.m in Sources */,
9A392EE81C1CDD530072C10A /* CLAboutUsViewController.m in Sources */,
9AF9A16B1C250AB300EE7C2A /* Reachability.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

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

Binary file not shown.

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

@ -2,4 +2,32 @@
<Bucket
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
scope = "1"
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Clocker/Preferences/CLPreferencesViewController.m"
timestampString = "472193139.144987"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "625"
endingLineNumber = "625"
landmarkName = "-getTimeZoneForLatitude:andLongitude:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

2
Clocker/AboutUsWindow/CLAboutUsView.xib

@ -119,7 +119,7 @@
<constraint firstAttribute="height" constant="20" id="2sg-Q1-h9h"/>
<constraint firstAttribute="width" constant="330" id="MHq-fu-8k6"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="the MIT License." id="JAy-Yp-MXm">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="the MIT License. Timezone search powered by GEONAMES." id="JAy-Yp-MXm">
<font key="font" size="10" name="HelveticaNeue-Light"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>

13
Clocker/ApplicationDelegate.m

@ -66,6 +66,8 @@ void *kContextActivePanel = &kContextActivePanel;
[iVersion sharedInstance].appStoreID = 1056643111;
[iRate sharedInstance].useAllAvailableLanguages = NO;
[iVersion sharedInstance].useAllAvailableLanguages = NO;
[[iRate sharedInstance] setVerboseLogging:NO];
[[iVersion sharedInstance] setVerboseLogging:NO];
}
#pragma mark - NSApplicationDelegate
@ -76,16 +78,6 @@ void *kContextActivePanel = &kContextActivePanel;
NSMutableArray *newDefaults = [[NSMutableArray alloc] init];
if (defaultPreference.count == 0)
{
NSDictionary *defaultDictionary = @{CLTimezoneName : [NSTimeZone systemTimeZone].name, CLCustomLabel : CLEmptyString};
newDefaults = [[NSMutableArray alloc] initWithObjects:defaultDictionary, nil];
[[NSUserDefaults standardUserDefaults] setObject:newDefaults forKey:CLDefaultPreferenceKey];
}
[defaultPreference enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[NSString class]]) {
@ -116,6 +108,7 @@ void *kContextActivePanel = &kContextActivePanel;
[[Crashlytics sharedInstance] setDebugMode:NO];
[Fabric with:@[[Crashlytics class]]];
//Setting up Parse
[Parse setApplicationId:@"F2ahd8J6sfjQMCc5z3xSy9kVK94PmKmH6hV2UsUK"

5
Clocker/Clocker-Info.plist

@ -46,5 +46,10 @@
<string>NSApplication</string>
<key>RequestsOpenAccess</key>
<string>YES</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>

49
Clocker/PanelController.m

@ -336,9 +336,9 @@ NSString *const CLTimezoneCellViewIdentifier = @"timeZoneCell";
}
cell.relativeDate.stringValue = [self getDateForTimeZone:self.defaultPreferences[row][CLTimezoneName]];
cell.relativeDate.stringValue = [self getDateForTimeZone:self.defaultPreferences[row][CLTimezoneID]];
cell.time.stringValue = [self getTimeForTimeZone:self.defaultPreferences[row][CLTimezoneName]];
cell.time.stringValue = [self getTimeForTimeZone:self.defaultPreferences[row][CLTimezoneID]];
cell.rowNumber = row;
@ -360,27 +360,30 @@ NSString *const CLTimezoneCellViewIdentifier = @"timeZoneCell";
return customLabel;
}
}
NSString *timezoneName = timeZoneDictionary[CLTimezoneName];
if (value) {
NSRange range = [timezoneName rangeOfString:@"/"];
NSRange underscoreRange = [timezoneName rangeOfString:@"_"];
if ([timeZoneDictionary[@"formattedAddress"] length] > 0)
{
return timeZoneDictionary[@"formattedAddress"];
}
else if (timeZoneDictionary[@"timezoneID"])
{
NSString *timezoneID = timeZoneDictionary[@"timezoneID"];
NSRange range = [timezoneID rangeOfString:@"/"];
if (range.location != NSNotFound)
{
timezoneName = [timezoneName substringFromIndex:range.location+1];
}
if (underscoreRange.location != NSNotFound)
{
timezoneName = [timezoneName stringByReplacingOccurrencesOfString:@"_"
withString:@" "];
timezoneID = [timezoneID substringWithRange:NSMakeRange(range.location+1, timezoneID.length-1 - range.location)];
}
return timezoneID;
}
return timezoneName;
else
{
return @"Error";
}
}
- (NSString *)getTimeForTimeZone:(NSString *)timezoneName
- (NSString *)getTimeForTimeZone:(NSString *)timezoneID
{
NSDate *currentDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
@ -390,7 +393,7 @@ NSString *const CLTimezoneCellViewIdentifier = @"timeZoneCell";
is24HourFormatSelected.boolValue ? [dateFormatter setDateFormat:@"HH:mm"] : [dateFormatter setDateFormat:@"hh:mm a"];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneName];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneID];
//In the format 22:10
return [dateFormatter stringFromDate:currentDate];
@ -442,25 +445,19 @@ NSString *const CLTimezoneCellViewIdentifier = @"timeZoneCell";
}
}
- (NSString *)getDateForTimeZone:(NSString *)timezoneName
- (NSString *)getDateForTimeZone:(NSString *)timezoneID
{
NSDate *currentDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = kCFDateFormatterShortStyle;
dateFormatter.timeStyle = kCFDateFormatterNoStyle;
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneName];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:timezoneID];
//In the format 22:10
return [self compareSystemDate:[self getLocalCurrentDate] toTimezoneDate:[dateFormatter stringFromDate:currentDate]];;
}
#pragma mark -
#pragma mark NSTableview Minor Customization when selecting rows
#pragma mark -
#pragma mark -
#pragma mark NSTableview Drag and Drop
#pragma mark -

104
Clocker/Preferences/CLPreferencesView.xib

@ -10,6 +10,7 @@
<outlet property="fontPopUp" destination="adA-dB-5Ok" id="FK1-Pq-eXW"/>
<outlet property="is24HourFormatSelected" destination="msw-L5-agF" id="Orm-wH-Yr8"/>
<outlet property="messageLabel" destination="KFC-NV-5A3" id="NKB-JY-Udb"/>
<outlet property="placeholderLabel" destination="Wb6-yr-Pw4" id="ilx-y4-XEw"/>
<outlet property="searchField" destination="biT-6m-ElR" id="Di3-QU-LGY"/>
<outlet property="themePopUp" destination="sfL-D2-aUX" id="G3Z-Nv-eVe"/>
<outlet property="timezonePanel" destination="6FL-fp-Ke1" id="SDq-Q4-hMb"/>
@ -42,6 +43,9 @@
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="gLH-wy-bCE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
</buttonCell>
<connections>
<action selector="removeFromFavourites:" target="-2" id="M3C-EF-9kQ"/>
@ -60,7 +64,7 @@
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="timezoneName" editable="NO" width="252.75" minWidth="80" maxWidth="1000" id="YaU-AD-fOu">
<tableColumn identifier="formattedAddress" editable="NO" width="252.75" minWidth="80" maxWidth="1000" id="YaU-AD-fOu">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Selected Timezone(s)">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@ -239,7 +243,7 @@
<rect key="frame" x="0.0" y="0.0" width="329" height="257"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" rowHeight="20" headerView="85y-4a-860" id="Q0t-hQ-orw">
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" rowHeight="20" headerView="85y-4a-860" id="Q0t-hQ-orw">
<rect key="frame" x="0.0" y="0.0" width="329" height="234"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
@ -247,8 +251,8 @@
<tableViewGridLines key="gridStyleMask" vertical="YES"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="availableTimezones" editable="NO" width="205.5" minWidth="40" maxWidth="1000" id="48H-5i-utq">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Timezone Name">
<tableColumn identifier="availableTimezones" editable="NO" width="326" minWidth="40" maxWidth="1000" id="48H-5i-utq">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Places">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -260,21 +264,13 @@
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="abbreviation" editable="NO" width="117.71875" minWidth="10" maxWidth="3.4028234663852886e+38" id="3Ii-DO-FaS">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Abbreviation">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="Wat-KA-MGe">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
</tableColumns>
<connections>
<binding destination="-2" name="enabled" keyPath="self.activityInProgress" id="Xk8-FS-aWk">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
<binding destination="-2" name="doubleClickTarget" keyPath="self" id="nBJ-qr-qEf">
<dictionary key="options">
<string key="NSSelectorName">addToFavorites:</string>
@ -291,7 +287,7 @@
<constraint firstAttribute="height" constant="257" id="SrA-bR-iMr"/>
</constraints>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="Ge2-Rs-CZ1">
<rect key="frame" x="1" y="241" width="327" height="15"/>
<rect key="frame" x="0.0" y="241" width="329" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="fHR-IX-Phl">
@ -304,45 +300,43 @@
</tableHeaderView>
</scrollView>
<button toolTip="Add a timezone" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hp6-CH-WJs">
<rect key="frame" x="2" y="-2" width="52" height="32"/>
<rect key="frame" x="8" y="4" width="60" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="r2L-5O-GZy"/>
<constraint firstAttribute="width" constant="40" id="yuH-LM-RAy"/>
<constraint firstAttribute="width" constant="60" id="yuH-LM-RAy"/>
</constraints>
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="x6l-8x-qnu">
<buttonCell key="cell" type="roundRect" title="Add" bezelStyle="roundedRect" imagePosition="left" alignment="center" borderStyle="border" inset="2" id="x6l-8x-qnu">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="HelveticaNeue-Light"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
<connections>
<action selector="addToFavorites:" target="-2" id="Mdg-7P-kDy"/>
</connections>
</button>
<button toolTip="Close Panel" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y2D-dA-scQ">
<rect key="frame" x="44" y="-2" width="65" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="53" id="VUu-N5-XON"/>
</constraints>
<buttonCell key="cell" type="push" title="Close" bezelStyle="rounded" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zLr-m7-UoC">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="HelveticaNeue-Light"/>
</buttonCell>
<connections>
<action selector="closePanel:" target="-2" id="44x-aT-3TO"/>
<binding destination="-2" name="enabled" keyPath="self.activityInProgress" id="aBp-GA-vQ3">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
<binding destination="-2" name="title" keyPath="self.buttonTitle" id="W5O-nY-Q3i"/>
</connections>
</button>
<searchField toolTip="Search a timezone" wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="biT-6m-ElR">
<rect key="frame" x="8" y="287" width="329" height="25"/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Enter Timezone Name" drawsBackground="YES" usesSingleLineMode="YES" id="ijc-z6-99E">
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Enter a city, state, country name" drawsBackground="YES" usesSingleLineMode="YES" id="ijc-z6-99E">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</searchFieldCell>
<connections>
<action selector="filterArray:" target="-2" id="f8p-qF-cfD"/>
<binding destination="-2" name="editable" keyPath="self.activityInProgress" id="qG8-46-bev">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</searchField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KFC-NV-5A3">
<rect key="frame" x="104" y="8" width="232" height="20"/>
<rect key="frame" x="76" y="7" width="256" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="rr3-gU-VUn"/>
</constraints>
@ -352,22 +346,46 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wb6-yr-Pw4">
<rect key="frame" x="98" y="134" width="259" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="QQQ-at-c1H"/>
<constraint firstAttribute="width" constant="255" id="ezl-af-c93"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="left" placeholderString="Please enter a timezone name" id="l4k-Vi-z4I">
<font key="font" size="13" name="HelveticaNeue-Light"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<progressIndicator wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="100" bezeled="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ifx-PO-gfq">
<rect key="frame" x="75" y="134" width="16" height="16"/>
<connections>
<binding destination="-2" name="animate" keyPath="self.activityInProgress" id="S3o-gJ-W9p"/>
<binding destination="-2" name="hidden" keyPath="self.activityInProgress" id="9pA-XX-dhd">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</progressIndicator>
</subviews>
<constraints>
<constraint firstItem="y2D-dA-scQ" firstAttribute="height" secondItem="hp6-CH-WJs" secondAttribute="height" id="0rm-Cz-pcN"/>
<constraint firstAttribute="trailing" secondItem="biT-6m-ElR" secondAttribute="trailing" constant="8" id="23X-dw-hpU"/>
<constraint firstAttribute="bottom" secondItem="y2D-dA-scQ" secondAttribute="bottom" constant="5" id="6bw-rs-ca4"/>
<constraint firstAttribute="trailing" secondItem="KFC-NV-5A3" secondAttribute="trailing" constant="11" id="B6V-vn-THO"/>
<constraint firstItem="Wb6-yr-Pw4" firstAttribute="leading" secondItem="ifx-PO-gfq" secondAttribute="trailing" constant="9" id="9cg-iz-7Dq"/>
<constraint firstAttribute="trailing" secondItem="KFC-NV-5A3" secondAttribute="trailing" constant="15" id="B6V-vn-THO"/>
<constraint firstItem="LM9-75-vkc" firstAttribute="top" secondItem="biT-6m-ElR" secondAttribute="bottom" constant="3" id="DZR-XO-6sm"/>
<constraint firstAttribute="bottom" secondItem="KFC-NV-5A3" secondAttribute="bottom" constant="8" id="FWx-F1-VK8"/>
<constraint firstItem="y2D-dA-scQ" firstAttribute="leading" secondItem="hp6-CH-WJs" secondAttribute="trailing" constant="2" id="JFg-6w-xDE"/>
<constraint firstAttribute="bottom" secondItem="KFC-NV-5A3" secondAttribute="bottom" constant="7" id="FWx-F1-VK8"/>
<constraint firstItem="KFC-NV-5A3" firstAttribute="leading" secondItem="hp6-CH-WJs" secondAttribute="trailing" constant="10" id="GYa-Tw-JN4"/>
<constraint firstItem="hp6-CH-WJs" firstAttribute="leading" secondItem="kXo-nl-oxR" secondAttribute="leading" constant="8" id="Oir-hL-Og8"/>
<constraint firstItem="biT-6m-ElR" firstAttribute="top" secondItem="kXo-nl-oxR" secondAttribute="top" constant="8" id="Y7N-oR-3KY"/>
<constraint firstItem="LM9-75-vkc" firstAttribute="leading" secondItem="kXo-nl-oxR" secondAttribute="leading" constant="8" id="ZJc-ws-AZR"/>
<constraint firstAttribute="bottom" secondItem="hp6-CH-WJs" secondAttribute="bottom" constant="5" id="hEn-h1-my5"/>
<constraint firstItem="biT-6m-ElR" firstAttribute="leading" secondItem="kXo-nl-oxR" secondAttribute="leading" constant="8" id="nhU-xR-AW2"/>
<constraint firstAttribute="trailing" secondItem="LM9-75-vkc" secondAttribute="trailing" constant="8" id="pMs-Ol-hsh"/>
<constraint firstItem="KFC-NV-5A3" firstAttribute="leading" secondItem="y2D-dA-scQ" secondAttribute="trailing" constant="3" id="z1R-FT-K8s"/>
<constraint firstItem="ifx-PO-gfq" firstAttribute="centerY" secondItem="Q0t-hQ-orw" secondAttribute="centerY" constant="2" id="roB-zz-kJF"/>
<constraint firstItem="Wb6-yr-Pw4" firstAttribute="centerY" secondItem="Q0t-hQ-orw" secondAttribute="centerY" id="uio-eQ-cpc"/>
<constraint firstItem="Wb6-yr-Pw4" firstAttribute="centerX" secondItem="Q0t-hQ-orw" secondAttribute="centerX" constant="55" id="y8D-5A-bLz"/>
</constraints>
</view>
<point key="canvasLocation" x="582.5" y="681"/>

5
Clocker/Preferences/CLPreferencesViewController.h

@ -10,11 +10,12 @@
@interface CLPreferencesViewController : NSViewController
@property (strong, nonatomic) NSMutableArray *timeZoneArray;
@property (strong, nonatomic) NSMutableArray *selectedTimeZones;
@property (strong, nonatomic) NSArray *filteredArray;
@property (strong, nonatomic) NSMutableArray *filteredArray;
@property (atomic, assign) BOOL launchOnLogin;
@property (atomic, strong) NSArray *fontFamilies;
@property (atomic, strong) NSArray *themes;
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@property (nonatomic, strong) NSString *buttonTitle;
@end

445
Clocker/Preferences/CLPreferencesViewController.m

@ -12,15 +12,19 @@
#import "ApplicationDelegate.h"
#import <QuartzCore/QuartzCore.h>
#import "CommonStrings.h"
#import "Reachability.h"
NSString *const CLSearchPredicateKey = @"SELF CONTAINS[cd]%@";
NSString *const CLPreferencesViewNibIdentifier = @"PreferencesWindow";
NSString *const CLPreferencesTimezoneNameIdentifier = @"timezoneName";
NSString *const CLPreferencesTimezoneNameIdentifier = @"formattedAddress";
NSString *const CLPreferencesAbbreviationIdentifier = @"abbreviation";
NSString *const CLPreferencesCustomLabelIdentifier = @"label";
NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones";
@interface CLPreferencesViewController ()
@property (weak) IBOutlet NSTextField *placeholderLabel;
@property (assign) BOOL activityInProgress;
@property (weak) IBOutlet NSTableView *timezoneTableView;
@property (strong) IBOutlet Panel *timezonePanel;
@ -31,7 +35,6 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
@property (weak) IBOutlet NSButton *is24HourFormatSelected;
@property (weak) IBOutlet NSTextField *messageLabel;
@property (weak) IBOutlet NSSlider *transparencySlider;
@end
@implementation CLPreferencesViewController
@ -41,19 +44,20 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
CALayer *viewLayer = [CALayer layer];
[viewLayer setBackgroundColor:CGColorCreateGenericRGB(255.0, 255.0, 255.0, 0.8)]; //RGB plus Alpha Channel
[self.view setWantsLayer:YES]; // view's backing store is using a Core Animation Layer
[self.view setWantsLayer:YES];
[self.view setLayer:viewLayer];
self.buttonTitle = @"Close";
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(refereshTimezoneTableView) name:CLCustomLabelChangedNotification object:nil];
self.placeholderLabel.hidden = YES;
[self refereshTimezoneTableView];
if (!self.timeZoneArray)
if (!self.filteredArray)
{
self.timeZoneArray = [[NSMutableArray alloc] initWithArray:[NSTimeZone knownTimeZoneNames]];
self.filteredArray = [[NSArray alloc] init];
self.filteredArray = [[NSMutableArray alloc] init];
}
self.messageLabel.stringValue = CLEmptyString;
@ -75,6 +79,8 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
}
}
//Certain fonts don't look good with constraints set
NSArray *fontsToRemove = [NSArray arrayWithObjects:@"Apple Chancery", @"Zapfino",
@ -114,10 +120,7 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
}
else
{
if (self.searchField.stringValue.length > 0) {
return self.filteredArray.count;
}
return self.timeZoneArray.count;
return self.filteredArray.count;
}
return 0;
@ -127,37 +130,25 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
{
if ([[tableColumn identifier] isEqualToString:CLPreferencesTimezoneNameIdentifier])
{
return self.selectedTimeZones[row][CLTimezoneName];
if ([self.selectedTimeZones[row][CLTimezoneName] length] > 0) {
return self.selectedTimeZones[row][CLTimezoneName];
}
return self.selectedTimeZones[row][CLTimezoneID];
}
else if([[tableColumn identifier] isEqualToString:CLPreferencesAvailableTimezoneIdentifier])
{
if (self.searchField.stringValue.length > 0)
if (row < self.filteredArray.count)
{
if (row < self.filteredArray.count) {
return self.filteredArray[row];
}
return [self.filteredArray[row] objectForKey:CLTimezoneName];
}
return self.timeZoneArray[row];
return nil;
}
else if([[tableColumn identifier] isEqualToString:CLPreferencesCustomLabelIdentifier])
{
return self.selectedTimeZones[row][CLCustomLabel];
}
if ([tableColumn.identifier isEqualToString:CLPreferencesAbbreviationIdentifier])
{
if (self.searchField.stringValue.length > 0)
{
if (row < self.filteredArray.count)
{
return [NSTimeZone timeZoneWithName:self.filteredArray[row]].abbreviation;
}
}
return [NSTimeZone timeZoneWithName:self.timeZoneArray[row]].abbreviation;
}
return nil;
}
@ -189,70 +180,60 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
- (IBAction)addToFavorites:(id)sender
{
self.activityInProgress = YES;
if ([self.buttonTitle isEqualToString:@"Close"])
{
self.filteredArray = [NSMutableArray array];
self.placeholderLabel.placeholderString = CLEmptyString;
[self.availableTimezoneTableView reloadData];
self.searchField.stringValue = CLEmptyString;
[self.timezonePanel close];
self.activityInProgress = NO;
return;
}
if (self.availableTimezoneTableView.selectedRow == -1)
{
self.messageLabel.stringValue = @"Please select a timezone!";
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO];
self.activityInProgress = NO;
return;
}
NSString *selectedTimezone;
if (self.selectedTimeZones.count > 10)
if (self.selectedTimeZones.count >= 10)
{
self.messageLabel.stringValue = @"Maximum 10 timezones allowed!";
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO];
NSLog(@"Maximum me ghusa");
self.activityInProgress = NO;
return;
}
for (NSDictionary *timezoneDictionary in self.selectedTimeZones)
{
NSString *name = timezoneDictionary[CLTimezoneName];
NSString *name = timezoneDictionary[@"place_id"];
NSString *selectedPlaceID = [self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:@"place_id"];
if (self.searchField.stringValue.length > 0) {
if ([name isEqualToString:self.filteredArray[self.availableTimezoneTableView.selectedRow]])
if ([name isKindOfClass:[NSString class]] &&
[name isEqualToString:selectedPlaceID])
{
self.messageLabel.stringValue = @"Timezone has already been selected!";
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO];
self.activityInProgress = NO;
return;
}
}
else if ([name isEqualToString:self.timeZoneArray[self.availableTimezoneTableView.selectedRow]])
{
self.messageLabel.stringValue = @"Timezone has already been selected!";
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(clearLabel) userInfo:nil repeats:NO];
return;
}
}
selectedTimezone = self.searchField.stringValue.length > 0 ?
self.filteredArray[self.availableTimezoneTableView.selectedRow] :
self.timeZoneArray[self.availableTimezoneTableView.selectedRow];
NSDictionary *newTimezoneToAdd = @{CLTimezoneName : selectedTimezone,
CLCustomLabel : CLEmptyString};
[self.selectedTimeZones addObject:newTimezoneToAdd];
NSArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults] objectForKey:CLDefaultPreferenceKey];
NSMutableArray *newDefaults;
if (defaultTimeZones == nil)
{
defaultTimeZones = [[NSMutableArray alloc] init];
}
newDefaults = [[NSMutableArray alloc] initWithArray:defaultTimeZones];
selectedTimezone = self.filteredArray[self.availableTimezoneTableView.selectedRow];
[newDefaults addObject:newTimezoneToAdd];
self.searchField.stringValue = CLEmptyString;
[[NSUserDefaults standardUserDefaults] setObject:newDefaults forKey:CLDefaultPreferenceKey];
[self.timezoneTableView reloadData];
[self refreshMainTableview];
[self.timezonePanel close];
[self getTimeZoneForLatitude:[self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:@"latitude"] andLongitude:[self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:@"longitude"]];
}
- (void)clearLabel
@ -260,14 +241,8 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
self.messageLabel.stringValue = CLEmptyString;
}
- (IBAction)closePanel:(id)sender
{
[self.timezonePanel close];
}
- (IBAction)removeFromFavourites:(id)sender
{
NSMutableArray *itemsToRemove = [NSMutableArray array];
if (self.timezoneTableView.selectedRow == -1)
@ -299,7 +274,6 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
if (theEvent.keyCode == 53) {
[self.timezonePanel close];
}
}
-(void)keyUp:(NSEvent *)theEvent
@ -311,15 +285,25 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
- (IBAction)filterArray:(id)sender
{
self.filteredArray = [NSMutableArray array];
if (self.searchField.stringValue.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:CLSearchPredicateKey, self.searchField.stringValue];
if (self.searchField.stringValue.length > 0)
{
[self callGoogleAPiWithSearchString:self.searchField.stringValue];
}
else
{
if (self.dataTask.state == NSURLSessionTaskStateRunning) {
[self.dataTask cancel];
}
self.filteredArray = [self.timeZoneArray filteredArrayUsingPredicate:predicate];
self.placeholderLabel.placeholderString = CLEmptyString;
self.buttonTitle = @"Close";
}
[self.availableTimezoneTableView reloadData];
}
- (IBAction)timeFormatSelectionChanged:(id)sender {
NSButton *is24HourFormatSelected = (NSButton *)sender;
@ -331,28 +315,35 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
- (void)refereshTimezoneTableView
{
NSMutableArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults] objectForKey:CLDefaultPreferenceKey];
self.selectedTimeZones = [[NSMutableArray alloc] initWithArray:defaultTimeZones];
[self.timezoneTableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *defaultTimeZones = [[NSUserDefaults standardUserDefaults]
objectForKey:CLDefaultPreferenceKey];
self.selectedTimeZones = [[NSMutableArray alloc] initWithArray:defaultTimeZones];
[self.timezoneTableView reloadData];
});
}
- (void)refreshMainTableview
{
ApplicationDelegate *appDelegate = [[NSApplication sharedApplication] delegate];
PanelController *panelController = appDelegate.panelController;
[panelController updateDefaultPreferences];
[panelController.mainTableview reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
ApplicationDelegate *appDelegate = [[NSApplication sharedApplication] delegate];
PanelController *panelController = appDelegate.panelController;
[panelController updateDefaultPreferences];
[panelController.mainTableview reloadData];
});
}
#pragma mark Reordering
- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:CLDragSessionKey] owner:self];
@ -391,56 +382,6 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
return NSDragOperationEvery;
}
- (BOOL)launchOnLogin
{
LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL);
NSArray* loginItems = CFBridgingRelease(snapshotRef);
NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
for (id item in loginItems) {
LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;
CFURLRef itemURLRef;
itemURLRef = LSSharedFileListItemCopyResolvedURL(itemRef, 0, NULL);
NSURL *itemURL = (NSURL *)CFBridgingRelease(itemURLRef);
if ([itemURL isEqual:bundleURL]) {
return YES;
}
}
return NO;
}
-(void)setLaunchOnLogin:(BOOL)launchOnLogin
{
NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (launchOnLogin) {
NSDictionary *properties;
properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"com.apple.loginitem.HideOnLaunch"];
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (__bridge CFURLRef)bundleURL, (__bridge CFDictionaryRef)properties,NULL);
if (itemRef) {
CFRelease(itemRef);
}
} else {
LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL);
NSArray* loginItems = CFBridgingRelease(snapshotRef);
for (id item in loginItems) {
LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;
CFURLRef itemURLRef = LSSharedFileListItemCopyResolvedURL(itemRef, 0, NULL);
NSURL *itemURL = (NSURL *)CFBridgingRelease(itemURLRef);
if ([itemURL isEqual:bundleURL]) {
LSSharedFileListItemRemove(loginItemsListRef, itemRef);
}
}
}
}
- (IBAction)changeFont:(id)sender
{
ApplicationDelegate *appDelegate = [[NSApplication sharedApplication] delegate];
@ -455,7 +396,6 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
PanelController *panelController = appDelegate.panelController;
[panelController.backgroundView setNeedsDisplay:YES];
if ([[popUpButtonTitle titleOfSelectedItem] isEqualToString:@"Black"]) {
panelController.shutdownButton.image = [NSImage imageNamed:@"PowerIcon-White"];
panelController.preferencesButton.image = [NSImage imageNamed:@"Settings-White"];
@ -467,9 +407,232 @@ NSString *const CLPreferencesAvailableTimezoneIdentifier = @"availableTimezones"
}
[panelController.mainTableview reloadData];
}
- (void)callGoogleAPiWithSearchString:(NSString *)searchString
{
if (self.dataTask.state == NSURLSessionTaskStateRunning) {
[self.dataTask cancel];
}
self.placeholderLabel.hidden = NO;
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
if (networkStatus == NotReachable)
{
self.placeholderLabel.placeholderString = @"You're offline, maybe?";
self.buttonTitle = @"Close";
return;
}
self.activityInProgress = YES;
self.placeholderLabel.placeholderString = [NSString stringWithFormat:@"Searching for '%@'", searchString];
NSArray* words = [searchString componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
searchString = [words componentsJoinedByString:@""];
NSString *urlString = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/geocode/json?address=%@&key=AIzaSyCyf2knCi6KiKuDJLYDBD3Odq5dt4c-_KI", searchString];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"GET";
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSError *error = nil;
if (!error) {
self.dataTask= [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
NSLog(@"Status Code:%zd", httpResp.statusCode);
if (httpResp.statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
self.placeholderLabel.placeholderString = CLEmptyString;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:nil];
if ([json[@"status"] isEqualToString:@"ZERO_RESULTS"]) {
self.placeholderLabel.placeholderString = @"No results found!";
self.activityInProgress = NO;
return;
}
for (NSDictionary *dictionary in json[@"results"])
{
NSDictionary *latLang = [[dictionary objectForKey:@"geometry"] objectForKey:@"location"];
NSString *latitude = latLang[@"lat"];
NSString *longitude = latLang[@"lng"];
NSString *formattedAddress = [dictionary objectForKey:@"formatted_address"];
NSDictionary *totalPackage = @{@"latitude":latitude,
@"longitude" : longitude,
CLTimezoneName:formattedAddress,
@"customLabel" : @"",
@"timezoneID" : @"",
@"placeID" : dictionary[@"place_id"]};
[self.filteredArray addObject:totalPackage];
}
self.activityInProgress = NO;
[self.availableTimezoneTableView reloadData];
self.buttonTitle = @"Add";
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
self.placeholderLabel.placeholderString = [error.localizedDescription isEqualToString:@"The Internet connection appears to be offline."] ?
@"You're offline, maybe?" : @"Try again, maybe?";
self.activityInProgress = NO;
});
}
}
}];
[self.dataTask resume];
}
}
- (void)getTimeZoneForLatitude:(NSString *)latitude andLongitude:(NSString *)longitude
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
if (networkStatus == NotReachable)
{
dispatch_async(dispatch_get_main_queue(), ^{
self.placeholderLabel.placeholderString = @"You're offline, maybe?";
self.activityInProgress = NO;
self.buttonTitle = @"Close";
self.filteredArray = [NSMutableArray array];
[self.availableTimezoneTableView reloadData];
});
return;
}
self.searchField.placeholderString = [NSString stringWithFormat:@"Adding %@", [self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:CLTimezoneName]];
self.placeholderLabel.placeholderString = @"Retrieving timezone data";
self.availableTimezoneTableView.hidden = YES;
NSString *urlString = [NSString stringWithFormat:@"http://api.geonames.org/timezoneJSON?lat=%@&lng=%@&username=abhishaker17", latitude, longitude];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"GET";
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSError *error = nil;
if (!error) {
self.dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:nil];
if (json.count == 0) {
self.placeholderLabel.placeholderString = @"No results found";
return;
}
NSString *filteredAddress = [self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:CLTimezoneName];
NSRange range = [filteredAddress rangeOfString:@","];
if (range.location != NSNotFound)
{
filteredAddress = [[self.filteredArray[self.availableTimezoneTableView.selectedRow] objectForKey:CLTimezoneName ] substringWithRange:NSMakeRange(0, range.location)];
}
NSDictionary *newTimezone = @{CLTimezoneID: json[@"timezoneId"],
@"sunriseTime" : json[@"sunrise"],
@"sunsetTime": json[@"sunset"],
CLCustomLabel : @"",
CLTimezoneName : filteredAddress};
NSArray *defaultPreference = [[NSUserDefaults standardUserDefaults] objectForKey:CLDefaultPreferenceKey];
if (defaultPreference == nil)
{
defaultPreference = [[NSMutableArray alloc] init];
}
NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:defaultPreference];
[newArray addObject:newTimezone];
[[NSUserDefaults standardUserDefaults] setObject:newArray forKey:CLDefaultPreferenceKey];
self.filteredArray = [NSMutableArray array];
[self.availableTimezoneTableView reloadData];
[self refereshTimezoneTableView];
[self refreshMainTableview];
[self.timezonePanel close];
self.availableTimezoneTableView.hidden = NO;
self.placeholderLabel.placeholderString = CLEmptyString;
self.searchField.placeholderString = @"Enter a city, state or country name";
self.activityInProgress = NO;
});
}
}
else
{
self.placeholderLabel.placeholderString = [error.localizedDescription isEqualToString:@"The Internet connection appears to be offline."] ?
@"You're offline, maybe?" : @"Try again, maybe?";
self.activityInProgress = NO;
}
}];
[self.dataTask resume];
}
}
@end

61
Clocker/Reachability/Reachability.h

@ -0,0 +1,61 @@
/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum : NSInteger {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
extern NSString *kReachabilityChangedNotification;
@interface Reachability : NSObject
/*!
* Use to check the reachability of a given host name.
*/
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
/*!
* Use to check the reachability of a given IP address.
*/
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
/*!
* Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
*/
+ (instancetype)reachabilityForInternetConnection;
/*!
* Checks whether a local WiFi connection is available.
*/
+ (instancetype)reachabilityForLocalWiFi;
/*!
* Start listening for reachability notifications on the current run loop.
*/
- (BOOL)startNotifier;
- (void)stopNotifier;
- (NetworkStatus)currentReachabilityStatus;
/*!
* WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
*/
- (BOOL)connectionRequired;
@end

269
Clocker/Reachability/Reachability.m

@ -0,0 +1,269 @@
/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <CoreFoundation/CoreFoundation.h>
#import "Reachability.h"
NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
#pragma mark - Supporting functions
#define kShouldPrintReachabilityFlags 1
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
{
#if kShouldPrintReachabilityFlags
NSLog(@"Reachability Flag Status: %c %c%c%c%c%c%c%c %s\n",
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
comment
);
#endif
}
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
Reachability* noteObject = (__bridge Reachability *)info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
}
#pragma mark - Reachability implementation
@implementation Reachability
{
BOOL _alwaysReturnLocalWiFiStatus; //default is NO
SCNetworkReachabilityRef _reachabilityRef;
}
+ (instancetype)reachabilityWithHostName:(NSString *)hostName
{
Reachability* returnValue = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if (reachability != NULL)
{
returnValue= [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
returnValue->_alwaysReturnLocalWiFiStatus = NO;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
Reachability* returnValue = NULL;
if (reachability != NULL)
{
returnValue = [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
returnValue->_alwaysReturnLocalWiFiStatus = NO;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityForInternetConnection
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress:&zeroAddress];
}
+ (instancetype)reachabilityForLocalWiFi
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
Reachability* returnValue = [self reachabilityWithAddress: &localWifiAddress];
if (returnValue != NULL)
{
returnValue->_alwaysReturnLocalWiFiStatus = YES;
}
return returnValue;
}
#pragma mark - Start and stop notifier
- (BOOL)startNotifier
{
BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
{
returnValue = YES;
}
}
return returnValue;
}
- (void)stopNotifier
{
if (_reachabilityRef != NULL)
{
SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
}
- (void)dealloc
{
[self stopNotifier];
if (_reachabilityRef != NULL)
{
CFRelease(_reachabilityRef);
}
}
#pragma mark - Network Flag Handling
- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
NetworkStatus returnValue = NotReachable;
if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
{
returnValue = ReachableViaWiFi;
}
return returnValue;
}
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// The target host is not reachable.
return NotReachable;
}
NetworkStatus returnValue = NotReachable;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
/*
If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
*/
returnValue = ReachableViaWiFi;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
/*
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
*/
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
/*
... and no [user] intervention is needed...
*/
returnValue = ReachableViaWiFi;
}
}
return returnValue;
}
- (BOOL)connectionRequired
{
NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}
- (NetworkStatus)currentReachabilityStatus
{
NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");
NetworkStatus returnValue = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
if (_alwaysReturnLocalWiFiStatus)
{
returnValue = [self localWiFiStatusForFlags:flags];
}
else
{
returnValue = [self networkStatusForFlags:flags];
}
}
return returnValue;
}
@end

1
Clocker/Utilities/CommonStrings.h

@ -17,5 +17,6 @@ extern NSString *const CLCustomLabel;
extern NSString *const CL24hourFormatSelectedKey;
extern NSString *const CLDragSessionKey;
extern NSString *const CLCustomLabelChangedNotification;
extern NSString *const CLTimezoneID;
@end

3
Clocker/Utilities/CommonStrings.m

@ -12,7 +12,8 @@
NSString *const CLEmptyString = @"";
NSString *const CLDefaultPreferenceKey = @"defaultPreferences";
NSString *const CLTimezoneName = @"timezoneName";
NSString *const CLTimezoneName = @"formattedAddress";
NSString *const CLTimezoneID = @"timezoneID";
NSString *const CLCustomLabel = @"customLabel";
NSString *const CL24hourFormatSelectedKey = @"is24HourFormatSelected";
NSString *const CLDragSessionKey = @"public.text";

Loading…
Cancel
Save