Browse Source

Merge branch 'master' of https://github.com/n0shake/Clocker

pull/92/head
Abhishek 4 years ago
parent
commit
5d84fcd6df
  1. 11
      Clocker/Clocker.xcodeproj/project.pbxproj
  2. 24
      Clocker/Clocker.xcodeproj/xcuserdata/ban.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  3. 59
      Clocker/Clocker/en.lproj/Panel.xib
  4. 2
      Clocker/ClockerUITests/AboutUsTests.swift
  5. 6
      Clocker/ClockerUITests/FloatingWindowTests.swift
  6. 1
      Clocker/Dependencies/iVersion/iVersion.m
  7. 62
      Clocker/Events and Reminders/CalendarHandler.swift
  8. 38
      Clocker/Media.xcassets/Accent Color.colorset/Contents.json
  9. 6
      Clocker/Media.xcassets/Contents.json
  10. 9
      Clocker/Media.xcassets/Pin/Float-White.imageset/Contents.json
  11. BIN
      Clocker/Media.xcassets/Pin/Float-White.imageset/PinIconWhite.png
  12. BIN
      Clocker/Media.xcassets/Pin/Float-White.imageset/Pin_1x.png
  13. BIN
      Clocker/Media.xcassets/Pin/Float-White.imageset/info panel detach button_Normal@2x.png
  14. 9
      Clocker/Media.xcassets/Pin/Float.imageset/Contents.json
  15. BIN
      Clocker/Media.xcassets/Pin/Float.imageset/PinIcon.png
  16. BIN
      Clocker/Media.xcassets/Pin/Float.imageset/Pin_Light_1x.png
  17. BIN
      Clocker/Media.xcassets/Pin/Float.imageset/light-mode.png
  18. 25
      Clocker/Media.xcassets/Pin/Pin.imageset/Contents.json
  19. BIN
      Clocker/Media.xcassets/Pin/Pin.imageset/PinIcon.png
  20. BIN
      Clocker/Media.xcassets/Pin/Pin.imageset/PinIconWhite.png
  21. BIN
      Clocker/Media.xcassets/Pin/Pin.imageset/Pin_1x.png
  22. BIN
      Clocker/Media.xcassets/Pin/Pin.imageset/info panel detach button_Normal@2x.png
  23. BIN
      Clocker/Media.xcassets/Pin/Pin.imageset/light-mode.png
  24. 24
      Clocker/Media.xcassets/Power Icon/Power.imageset/Contents.json
  25. BIN
      Clocker/Media.xcassets/Power Icon/Power.imageset/More-Dark.png
  26. BIN
      Clocker/Media.xcassets/Power Icon/Power.imageset/More.png
  27. BIN
      Clocker/Media.xcassets/Power Icon/Power.imageset/PowerIcon 2.png
  28. BIN
      Clocker/Media.xcassets/Power Icon/Power.imageset/PowerIcon.png
  29. 8
      Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/Contents.json
  30. BIN
      Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/More-Dark.png
  31. BIN
      Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/PowerIcon 2.png
  32. 8
      Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/Contents.json
  33. BIN
      Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/More.png
  34. BIN
      Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/PowerIcon.png
  35. 54
      Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/Contents.json
  36. BIN
      Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share1x.png
  37. BIN
      Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share1x_light.png
  38. BIN
      Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share2x.png
  39. BIN
      Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share2x_light.png
  40. 9
      Clocker/Media.xcassets/Sharing/Sharing.imageset/Contents.json
  41. BIN
      Clocker/Media.xcassets/Sharing/Sharing.imageset/noun_1020875_cc.png
  42. BIN
      Clocker/Media.xcassets/Sharing/Sharing.imageset/share1x_light.png
  43. BIN
      Clocker/Media.xcassets/Sharing/Sharing.imageset/share2x_light.png
  44. 9
      Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/Contents.json
  45. BIN
      Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/Sharing_Dark.png
  46. BIN
      Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/share1x.png
  47. BIN
      Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/share2x.png
  48. 42
      Clocker/Menu Bar/StatusContainerView.swift
  49. 58
      Clocker/Menu Bar/StatusItemView.swift
  50. 47
      Clocker/Onboarding/Onboarding.storyboard
  51. 11
      Clocker/Onboarding/OnboardingParentViewController.swift
  52. 33
      Clocker/Overall App/Themer.swift
  53. 257
      Clocker/Overall App/VersionUpdateHandler.swift
  54. 26
      Clocker/Panel/Data Layer/TimezoneDataOperations.swift
  55. 4
      Clocker/Panel/Notes Popover/NotesPopover.swift
  56. 25
      Clocker/Panel/Notes Popover/NotesPopover.xib
  57. 10
      Clocker/Panel/PanelController.swift
  58. 71
      Clocker/Panel/ParentPanelController.swift
  59. 65
      Clocker/Panel/UI/FloatingWindow.xib
  60. 12
      Clocker/Panel/UI/TimezoneDataSource.swift
  61. 2
      Clocker/Preferences/About/AboutViewController.swift
  62. 84
      Clocker/Preferences/App Feedback/AppFeedbackWindow.xib
  63. 43
      Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift
  64. 11
      Clocker/Preferences/Calendar/CalendarViewController.swift
  65. 15
      Clocker/Preferences/OneWindowController.swift
  66. 34
      Clocker/Preferences/Preferences.storyboard

11
Clocker/Clocker.xcodeproj/project.pbxproj

@ -821,7 +821,6 @@
DD4F7BF913C30F9F00825C6E = {
isa = PBXGroup;
children = (
9AEC7108249A93DA006520FA /* Keys.plist */,
35C36F9B2259EC97002FA5C6 /* Events and Reminders */,
35C36F382259D80C002FA5C6 /* Overall App */,
35C36F242259D64D002FA5C6 /* Panel */,
@ -1115,7 +1114,6 @@
9A13BAD61CA87F08007C6CBE /* Panel.xib in Resources */,
35C36F6B2259E0E1002FA5C6 /* FloatingWindow.xib in Resources */,
35C36F17225961DA002FA5C6 /* DateTools.bundle in Resources */,
9AEC7109249A93DA006520FA /* Keys.plist in Resources */,
35C36EF322595F14002FA5C6 /* WelcomeView.xib in Resources */,
35C36EF822595F14002FA5C6 /* Onboarding.storyboard in Resources */,
35C36F612259DE67002FA5C6 /* NotesPopover.xib in Resources */,
@ -1440,6 +1438,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "Accent Color";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@ -1454,7 +1453,7 @@
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 77;
CURRENT_PROJECT_VERSION = 79;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
@ -1925,6 +1924,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "Accent Color";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@ -1939,7 +1939,7 @@
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 77;
CURRENT_PROJECT_VERSION = 79;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
@ -1988,6 +1988,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "Accent Color";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@ -2002,7 +2003,7 @@
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 77;
CURRENT_PROJECT_VERSION = 79;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (

24
Clocker/Clocker.xcodeproj/xcuserdata/ban.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@ -1,5 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "F515D608-9FB6-4230-BDAA-714D2FAB3B77"
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
uuid = "0963511F-240E-487A-8C30-82699394C21B"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
breakpointStackSelectionBehavior = "1"
scope = "1"
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
<BreakpointContent
uuid = "4624F314-95A9-4ACC-A82C-CB1A1481BAA4"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

59
Clocker/Clocker/en.lproj/Panel.xib

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17132" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17132"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -38,7 +38,7 @@
<windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES" ignoresCycle="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="1000" y="379" width="350" height="460"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1025"/>
<view key="contentView" focusRingType="none" id="6" customClass="BackgroundPanelView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="350" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -47,19 +47,19 @@
<rect key="frame" x="0.0" y="0.0" width="350" height="460"/>
<subviews>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="96" horizontalPageScroll="1" verticalLineScroll="96" verticalPageScroll="1" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="light" translatesAutoresizingMaskIntoConstraints="NO" id="4Gd-Nv-fXr">
<rect key="frame" x="0.0" y="195" width="350" height="265"/>
<rect key="frame" x="-20" y="195" width="370" height="265"/>
<clipView key="contentView" focusRingType="none" drawsBackground="NO" copiesOnScroll="NO" id="4MZ-Di-yNR">
<rect key="frame" x="0.0" y="0.0" width="350" height="265"/>
<rect key="frame" x="0.0" y="0.0" width="370" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="95" viewBased="YES" id="dFw-ts-8OZ" customClass="PanelTableView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="350" height="265"/>
<rect key="frame" x="0.0" y="0.0" width="370" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="1"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="347" minWidth="303" maxWidth="1000" id="LTt-db-Dwv">
<tableColumn width="338" minWidth="303" maxWidth="1000" id="LTt-db-Dwv">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -72,7 +72,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="timeZoneCell" id="qbN-ba-fho" customClass="TimezoneCellView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="0.0" width="347" height="111"/>
<rect key="frame" x="11" y="0.0" width="347" height="111"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" verticalCompressionResistancePriority="749" tag="102" preferredMaxLayoutWidth="72" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QUd-7D-q14">
@ -208,7 +208,7 @@
</connections>
</tableCellView>
<tableCellView identifier="addCell" id="rb3-TW-xSb" customClass="AddTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="112" width="347" height="100"/>
<rect key="frame" x="11" y="112" width="347" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AzA-5G-LR7">
@ -287,7 +287,7 @@
<rect key="frame" x="75" y="2" width="200" height="21"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WVY-D9-AAX">
<rect key="frame" x="-6" y="-7" width="108" height="32"/>
<rect key="frame" x="-7" y="-7" width="110" height="33"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="4zI-xY-iLf"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="96" id="weK-At-NNy"/>
@ -301,7 +301,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="w3d-CG-aBO">
<rect key="frame" x="98" y="-7" width="108" height="32"/>
<rect key="frame" x="97" y="-6" width="110" height="32"/>
<buttonCell key="cell" type="push" title="Yes!" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="VE1-Cu-JUr">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="Avenir-Light"/>
@ -411,7 +411,7 @@
<rect key="frame" x="0.0" y="40" width="350" height="30"/>
<subviews>
<datePicker focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zN8-JF-j7O">
<rect key="frame" x="203" y="2" width="137" height="26"/>
<rect key="frame" x="203" y="0.0" width="137" height="23"/>
<datePickerCell key="cell" focusRingType="none" alignment="left" drawsBackground="NO" datePickerStyle="textField" id="Zg1-OT-OMw">
<font key="font" size="13" name="Avenir-Roman"/>
<date key="date" timeIntervalSinceReferenceDate="-595929600">
@ -426,7 +426,7 @@
</connections>
</datePicker>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Vf2-uI-yf3">
<rect key="frame" x="7" y="6" width="196" height="19"/>
<rect key="frame" x="7" y="2" width="196" height="23"/>
<constraints>
<constraint firstAttribute="height" constant="15" id="cS7-i2-mHU"/>
</constraints>
@ -439,10 +439,9 @@
<constraints>
<constraint firstItem="zN8-JF-j7O" firstAttribute="leading" secondItem="Vf2-uI-yf3" secondAttribute="trailing" constant="2" id="AKG-Oj-pRQ"/>
<constraint firstAttribute="height" constant="30" id="ELw-ee-72z"/>
<constraint firstAttribute="bottom" secondItem="zN8-JF-j7O" secondAttribute="bottom" constant="2" id="T2p-SQ-dvn"/>
<constraint firstItem="Vf2-uI-yf3" firstAttribute="leading" secondItem="C7R-Dq-MFr" secondAttribute="leading" constant="9" id="UPM-fg-1uv"/>
<constraint firstItem="Vf2-uI-yf3" firstAttribute="centerY" secondItem="C7R-Dq-MFr" secondAttribute="centerY" id="Wno-LD-sb9"/>
<constraint firstItem="zN8-JF-j7O" firstAttribute="top" secondItem="C7R-Dq-MFr" secondAttribute="top" constant="2" id="cdB-o2-dPr"/>
<constraint firstItem="zN8-JF-j7O" firstAttribute="firstBaseline" secondItem="Vf2-uI-yf3" secondAttribute="firstBaseline" id="Zwq-PS-gg2"/>
<constraint firstAttribute="trailing" secondItem="zN8-JF-j7O" secondAttribute="trailing" constant="10" id="ci5-6v-klf"/>
</constraints>
</customView>
@ -455,22 +454,22 @@
<constraint firstAttribute="height" constant="25" id="WSi-Xj-Kfl"/>
<constraint firstAttribute="width" constant="30" id="j2s-C4-pK5"/>
</constraints>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="PowerIcon" imagePosition="only" alignment="center" alternateImage="PowerIcon" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Fp1-89-Nwm">
<behavior key="behavior" lightByContents="YES"/>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="PowerIcon" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Fp1-89-Nwm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<accessibility identifier="Close"/>
<connections>
<action selector="terminate:" target="-1" id="ZY8-sG-rkC"/>
<action selector="showMoreOptions:" target="-2" id="xl5-rm-4JK"/>
</connections>
</button>
<button toolTip="Switch between Menubar/Floating mode." verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YXE-4J-5cn">
<rect key="frame" x="278" y="10" width="29" height="19"/>
<rect key="frame" x="275" y="10" width="29" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="29" id="fWo-31-i3M"/>
<constraint firstAttribute="height" constant="18" id="v7I-PR-eTK"/>
</constraints>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="Float" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="iwC-c9-CBS">
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="Float-White" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="iwC-c9-CBS">
<behavior key="behavior" lightByContents="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
@ -480,12 +479,12 @@
</connections>
</button>
<button toolTip="Share Clocker!" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hc7-fH-V7i">
<rect key="frame" x="248" y="7" width="30" height="26"/>
<rect key="frame" x="240" y="10" width="30" height="21"/>
<constraints>
<constraint firstAttribute="height" constant="25" id="Bnf-E1-uaE"/>
<constraint firstAttribute="height" constant="20" id="Bnf-E1-uaE"/>
<constraint firstAttribute="width" constant="30" id="pke-4M-ob5"/>
</constraints>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="NSShareTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="jZm-RN-msv">
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="SharingDarkIcon" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="jZm-RN-msv">
<behavior key="behavior" lightByContents="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
@ -514,13 +513,13 @@
</subviews>
<constraints>
<constraint firstItem="Ctq-BV-GPN" firstAttribute="centerY" secondItem="B8X-sx-cjT" secondAttribute="centerY" id="6Q7-jc-cTL"/>
<constraint firstItem="YXE-4J-5cn" firstAttribute="leading" secondItem="Hc7-fH-V7i" secondAttribute="trailing" id="GF2-UV-dDg"/>
<constraint firstItem="YXE-4J-5cn" firstAttribute="leading" secondItem="Hc7-fH-V7i" secondAttribute="trailing" constant="5" id="GF2-UV-dDg"/>
<constraint firstItem="YXE-4J-5cn" firstAttribute="centerY" secondItem="B8X-sx-cjT" secondAttribute="centerY" id="OHe-Tc-b0V"/>
<constraint firstAttribute="height" constant="40" id="iYW-fj-EE2"/>
<constraint firstItem="1cR-pI-osG" firstAttribute="centerY" secondItem="B8X-sx-cjT" secondAttribute="centerY" id="oVJ-Xa-cTw"/>
<constraint firstAttribute="trailing" secondItem="1cR-pI-osG" secondAttribute="trailing" constant="11" id="rb9-gW-QZS"/>
<constraint firstItem="1cR-pI-osG" firstAttribute="leading" secondItem="YXE-4J-5cn" secondAttribute="trailing" constant="2" id="tCt-DB-tt2"/>
<constraint firstItem="Hc7-fH-V7i" firstAttribute="centerY" secondItem="B8X-sx-cjT" secondAttribute="centerY" id="vPp-mQ-wgE"/>
<constraint firstItem="1cR-pI-osG" firstAttribute="leading" secondItem="YXE-4J-5cn" secondAttribute="trailing" constant="5" id="tCt-DB-tt2"/>
<constraint firstItem="Hc7-fH-V7i" firstAttribute="centerY" secondItem="B8X-sx-cjT" secondAttribute="centerY" constant="-1" id="vPp-mQ-wgE"/>
<constraint firstItem="Ctq-BV-GPN" firstAttribute="leading" secondItem="B8X-sx-cjT" secondAttribute="leading" constant="8" id="ydm-oF-sVc"/>
</constraints>
</customView>
@ -570,10 +569,10 @@
<image name="Add Icon" width="700" height="700"/>
<image name="CurrentLocation" width="350" height="350"/>
<image name="Extra" width="700" height="700"/>
<image name="Float" width="700" height="700"/>
<image name="NSActionTemplate" width="14" height="14"/>
<image name="NSShareTemplate" width="11" height="16"/>
<image name="PowerIcon" width="270" height="270"/>
<image name="Float-White" width="15" height="13"/>
<image name="NSActionTemplate" width="17" height="15"/>
<image name="PowerIcon" width="350" height="350"/>
<image name="Remove" width="700" height="700"/>
<image name="SharingDarkIcon" width="19" height="22"/>
</resources>
</document>

2
Clocker/ClockerUITests/AboutUsTests.swift

@ -33,7 +33,7 @@ class AboutUsTests: XCTestCase {
tapAboutTab()
let appDisplayName = "CFBundleDisplayName".localizedString()
let expectedVersion = "\(appDisplayName) 20.05.01 (77)"
let expectedVersion = "\(appDisplayName) 20.05.01 (79)"
guard let presentVersion = app.windows["Clocker"].staticTexts["ClockerVersion"].value as? String else {
XCTFail("Present version not present")
return

6
Clocker/ClockerUITests/FloatingWindowTests.swift

@ -4,7 +4,7 @@ import XCTest
extension String {
func localizedString() -> String {
let bundle = Bundle(for: AboutUsTests.self)
let bundle = Bundle(for: FloatingWindowTests.self)
return NSLocalizedString(self, bundle: bundle, comment: "")
}
}
@ -144,6 +144,7 @@ class FloatingWindowTests: XCTestCase {
let appearanceTab = app.toolbars.buttons.element(boundBy: 1)
appearanceTab.click()
// Select Misc tab
let miscTab = app.tabs.element(boundBy: 1)
miscTab.click()
@ -159,6 +160,7 @@ class FloatingWindowTests: XCTestCase {
XCTAssertFalse(app.staticTexts["InformationLabel"].exists)
}
/// Make sure to ensure supplementary/relative date label is turned on!
func testMovingSlider() {
if app.buttons["Pin"].exists {
app.buttons["Pin"].click()
@ -167,7 +169,7 @@ class FloatingWindowTests: XCTestCase {
let floatingSlider = app.sliders["FloatingSlider"].exists
if floatingSlider {
let tomorrowPredicate = NSPredicate(format: "placeholderValue like %@", "Tomorrow")
let tomorrowPredicate = NSPredicate(format: "identifier like %@", "RelativeDate")
let tomorrow = app.tables.tableRows.staticTexts.matching(tomorrowPredicate)
var previousValues: [String] = []

1
Clocker/Dependencies/iVersion/iVersion.m

@ -69,7 +69,6 @@ static NSString *const iVersionLastRemindedKey = @"iVersionLastReminded";
static NSString *const iVersionMacAppStoreBundleID = @"com.apple.appstore";
static NSString *const iVersionAppLookupURLFormat = @"http://itunes.apple.com/%@/lookup";
static NSString *const iVersioniOSAppStoreURLFormat = @"itms-apps://itunes.apple.com/app/id%@";
static NSString *const iVersionMacAppStoreURLFormat = @"macappstore://itunes.apple.com/app/id%@";

62
Clocker/Events and Reminders/CalendarHandler.swift

@ -53,6 +53,68 @@ extension EventCenter {
return sourcesAndCalendars
}
func isThereAnUpcomingCalendarEvent() -> Bool {
if DataStore.shared().shouldDisplay(.showMeetingInMenubar) {
let filteredDates = EventCenter.sharedCenter().eventsForDate
let autoupdatingCal = EventCenter.sharedCenter().autoupdatingCalendar
guard let events = filteredDates[autoupdatingCal.startOfDay(for: Date())] else {
return false
}
for event in events {
if event.event.startDate.timeIntervalSinceNow > 0, !event.isAllDay {
let timeForEventToStart = event.event.startDate.timeIntervalSinceNow / 60
if timeForEventToStart > 30 {
print("Our next event: \(event.event.title ?? "Error") starts in \(timeForEventToStart) mins")
continue
}
return true
}
}
}
return false
}
/* Used for the compact menubar mode.
Returns a tuple with 0 as the header string and 1 as the subtitle string
*/
func separateFormat(event: EKEvent) -> (String, String)? {
guard let truncateLength = DataStore.shared().retrieve(key: CLTruncateTextLength) as? NSNumber, let eventTitle = event.title else {
return nil
}
let seconds = event.startDate.timeIntervalSinceNow
var formattedTitle: String = CLEmptyString
if eventTitle.count > truncateLength.intValue {
let truncateIndex = eventTitle.index(eventTitle.startIndex, offsetBy: truncateLength.intValue)
let truncatedTitle = String(eventTitle[..<truncateIndex])
formattedTitle.append(truncatedTitle)
formattedTitle.append("...")
} else {
formattedTitle.append(eventTitle)
}
var menubarText: String = CLEmptyString
let minutes = seconds / 60
if minutes > 2 {
let suffix = String(format: " in %0.f mins", minutes)
menubarText.append(suffix)
} else if minutes == 1 {
let suffix = String(format: " in %0.f min", minutes)
menubarText.append(suffix)
} else {
menubarText.append(" starts now.")
}
return (formattedTitle, menubarText)
}
func format(event: EKEvent) -> String {
guard let truncateLength = DataStore.shared().retrieve(key: CLTruncateTextLength) as? NSNumber, let eventTitle = event.title else {
return CLEmptyString

38
Clocker/Media.xcassets/Accent Color.colorset/Contents.json

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "extended-srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.999",
"green" : "0.000",
"red" : "0.092"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "extended-srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.109",
"green" : "0.958",
"red" : "0.071"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

6
Clocker/Media.xcassets/Contents.json

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

9
Clocker/Media.xcassets/Pin/Float-White.imageset/Contents.json vendored

@ -1,11 +1,12 @@
{
"images" : [
{
"filename" : "Pin_1x.png",
"idiom" : "universal",
"filename" : "PinIconWhite.png",
"scale" : "1x"
},
{
"filename" : "info panel detach button_Normal@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
@ -15,7 +16,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Pin/Float-White.imageset/PinIconWhite.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
Clocker/Media.xcassets/Pin/Float-White.imageset/Pin_1x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

BIN
Clocker/Media.xcassets/Pin/Float-White.imageset/info panel detach button_Normal@2x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

9
Clocker/Media.xcassets/Pin/Float.imageset/Contents.json vendored

@ -1,11 +1,12 @@
{
"images" : [
{
"filename" : "Pin_Light_1x.png",
"idiom" : "universal",
"filename" : "PinIcon.png",
"scale" : "1x"
},
{
"filename" : "light-mode.png",
"idiom" : "universal",
"scale" : "2x"
},
@ -15,7 +16,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Pin/Float.imageset/PinIcon.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

BIN
Clocker/Media.xcassets/Pin/Float.imageset/Pin_Light_1x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
Clocker/Media.xcassets/Pin/Float.imageset/light-mode.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

25
Clocker/Media.xcassets/Pin/Pin.imageset/Contents.json vendored

@ -5,29 +5,30 @@
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "1x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
],
"filename" : "Pin_1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "light-mode.png",
"idiom" : "universal",
"filename" : "PinIcon.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "PinIconWhite.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "info panel detach button_Normal@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
@ -35,18 +36,18 @@
"scale" : "3x"
},
{
"idiom" : "universal",
"scale" : "3x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Pin/Pin.imageset/PinIcon.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

BIN
Clocker/Media.xcassets/Pin/Pin.imageset/PinIconWhite.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
Clocker/Media.xcassets/Pin/Pin.imageset/Pin_1x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

BIN
Clocker/Media.xcassets/Pin/Pin.imageset/info panel detach button_Normal@2x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
Clocker/Media.xcassets/Pin/Pin.imageset/light-mode.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

24
Clocker/Media.xcassets/Power Icon/Power.imageset/Contents.json vendored

@ -5,29 +5,29 @@
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "1x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "More.png",
"idiom" : "universal",
"filename" : "PowerIcon.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "PowerIcon 2.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "More-Dark.png",
"idiom" : "universal",
"scale" : "2x"
},
{
@ -35,18 +35,18 @@
"scale" : "3x"
},
{
"idiom" : "universal",
"scale" : "3x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Power Icon/Power.imageset/More-Dark.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
Clocker/Media.xcassets/Power Icon/Power.imageset/More.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
Clocker/Media.xcassets/Power Icon/Power.imageset/PowerIcon 2.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

BIN
Clocker/Media.xcassets/Power Icon/Power.imageset/PowerIcon.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

8
Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/Contents.json vendored

@ -2,10 +2,10 @@
"images" : [
{
"idiom" : "universal",
"filename" : "PowerIcon 2.png",
"scale" : "1x"
},
{
"filename" : "More-Dark.png",
"idiom" : "universal",
"scale" : "2x"
},
@ -15,7 +15,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/More-Dark.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
Clocker/Media.xcassets/Power Icon/PowerIcon-White.imageset/PowerIcon 2.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

8
Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/Contents.json vendored

@ -2,10 +2,10 @@
"images" : [
{
"idiom" : "universal",
"filename" : "PowerIcon.png",
"scale" : "1x"
},
{
"filename" : "More.png",
"idiom" : "universal",
"scale" : "2x"
},
@ -15,7 +15,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/More.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
Clocker/Media.xcassets/Power Icon/PowerIcon.imageset/PowerIcon.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

54
Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/Contents.json vendored

@ -0,0 +1,54 @@
{
"images" : [
{
"filename" : "share1x_light.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "share1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "share2x_light.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "share2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

BIN
Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share1x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share1x_light.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share2x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
Clocker/Media.xcassets/Sharing/Sharing Dynamic.imageset/share2x_light.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

9
Clocker/Media.xcassets/Sharing/Sharing.imageset/Contents.json vendored

@ -1,12 +1,13 @@
{
"images" : [
{
"filename" : "share1x_light.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "share2x_light.png",
"idiom" : "universal",
"filename" : "noun_1020875_cc.png",
"scale" : "2x"
},
{
@ -15,7 +16,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Sharing/Sharing.imageset/noun_1020875_cc.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

BIN
Clocker/Media.xcassets/Sharing/Sharing.imageset/share1x_light.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
Clocker/Media.xcassets/Sharing/Sharing.imageset/share2x_light.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

9
Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/Contents.json vendored

@ -1,12 +1,13 @@
{
"images" : [
{
"filename" : "share1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "share2x.png",
"idiom" : "universal",
"filename" : "Sharing_Dark.png",
"scale" : "2x"
},
{
@ -15,7 +16,7 @@
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

BIN
Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/Sharing_Dark.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/share1x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
Clocker/Media.xcassets/Sharing/SharingDarkIcon.imageset/share2x.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

42
Clocker/Menu Bar/StatusContainerView.swift

@ -71,14 +71,21 @@ class StatusContainerView: NSView {
}
}
let timeBasedAttributes = [
NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
]
func containerWidth(for timezones: [Data]) -> CGFloat {
let compressedWidth = timezones.reduce(0.0) { (result, timezone) -> CGFloat in
if let timezoneObject = TimezoneData.customObject(from: timezone) {
let precalculatedWidth = Double(compactWidth(for: timezoneObject))
let operationObject = TimezoneDataOperations(with: timezoneObject)
let calculatedSize = compactModeTimeFont.size(operationObject.compactMenuSubtitle(), precalculatedWidth, attributes: timeAttributes)
return result + calculatedSize.width + bufferWidth
let calculatedSubtitleSize = compactModeTimeFont.size(operationObject.compactMenuSubtitle(), precalculatedWidth, attributes: timeBasedAttributes)
let calculatedTitleSize = compactModeTimeFont.size(operationObject.compactMenuTitle(), precalculatedWidth, attributes: timeBasedAttributes)
return result + max(calculatedTitleSize.width, calculatedSubtitleSize.width) + bufferWidth
}
return result + CGFloat(bufferCalculatedWidth())
@ -113,11 +120,25 @@ class StatusContainerView: NSView {
}
private func bestWidth(for timezone: TimezoneData) -> Int {
let operation = TimezoneDataOperations(with: timezone)
var textColor = hasDarkAppearance ? NSColor.white : NSColor.black
let bestSize = compactModeTimeFont.size(operation.compactMenuSubtitle(), Double(compactWidth(for: timezone)), attributes: timeAttributes)
if #available(macOS 10.16, *) {
textColor = NSColor.white
}
return Int(bestSize.width + bufferWidth)
let timeBasedAttributes = [
NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
]
let operation = TimezoneDataOperations(with: timezone)
let bestSize = compactModeTimeFont.size(operation.compactMenuSubtitle(),
Double(compactWidth(for: timezone)), attributes: timeBasedAttributes)
let bestTitleSize = compactModeTimeFont.size(operation.compactMenuTitle(), Double(compactWidth(for: timezone)), attributes: timeBasedAttributes)
return Int(max(bestSize.width, bestTitleSize.width) + bufferWidth)
}
func updateTime() {
@ -126,16 +147,25 @@ class StatusContainerView: NSView {
}
// See if frame's width needs any adjustment
adjustWidthIfNeccessary()
}
private func adjustWidthIfNeccessary() {
var newWidth: CGFloat = 0
subviews.forEach {
if let statusItem = $0 as? StatusItemView {
if let statusItem = $0 as? StatusItemView, statusItem.isHidden == false {
// Determine what's the best width required to display the current string.
let newBestWidth = CGFloat(bestWidth(for: statusItem.dataObject))
// Let's note if the current width is too small/correct
newWidth += statusItem.frame.size.width != newBestWidth ? newBestWidth : statusItem.frame.size.width
statusItem.frame = CGRect(x: statusItem.frame.origin.x,
y: statusItem.frame.origin.y,
width: newBestWidth,
height: statusItem.frame.size.height)
statusItem.updateTimeInMenubar()
}
}

58
Clocker/Menu Bar/StatusItemView.swift

@ -2,7 +2,7 @@
import Cocoa
private var defaultParagraphStyle: NSMutableParagraphStyle {
var defaultParagraphStyle: NSMutableParagraphStyle {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
paragraphStyle.lineBreakMode = .byTruncatingTail
@ -13,16 +13,24 @@ var compactModeTimeFont: NSFont {
return NSFont.monospacedDigitSystemFont(ofSize: 10, weight: .regular)
}
var timeAttributes: [NSAttributedString.Key: AnyObject] {
let textColor = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark" ? NSColor.white : NSColor.black
let attributes = [
NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
]
return attributes
extension NSView {
var hasDarkAppearance: Bool {
if #available(OSX 10.14, *) {
switch effectiveAppearance.name {
case .darkAqua, .vibrantDark, .accessibilityHighContrastDarkAqua, .accessibilityHighContrastVibrantDark:
return true
default:
return false
}
} else {
switch effectiveAppearance.name {
case .vibrantDark:
return true
default:
return false
}
}
}
}
class StatusItemView: NSView {
@ -34,8 +42,28 @@ class StatusItemView: NSView {
return TimezoneDataOperations(with: dataObject)
}
private var timeAttributes: [NSAttributedString.Key: AnyObject] {
var textColor = hasDarkAppearance ? NSColor.white : NSColor.black
if #available(macOS 10.16, *) {
textColor = NSColor.white
}
let attributes = [
NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
]
return attributes
}
private var textFontAttributes: [NSAttributedString.Key: Any] {
let textColor = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark" ? NSColor.white : NSColor.black
var textColor = hasDarkAppearance ? NSColor.white : NSColor.black
if #available(macOS 10.16, *) {
textColor = NSColor.white
}
let textFontAttributes = [
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10),
@ -81,6 +109,12 @@ class StatusItemView: NSView {
])
}
@available(OSX 10.14, *)
override func viewDidChangeEffectiveAppearance() {
super.viewDidChangeEffectiveAppearance()
updateTimeInMenubar()
}
func updateTimeInMenubar() {
locationView.attributedStringValue = NSAttributedString(string: operationsObject.compactMenuTitle(), attributes: textFontAttributes)
timeView.attributedStringValue = NSAttributedString(string: operationsObject.compactMenuSubtitle(), attributes: timeAttributes)

47
Clocker/Onboarding/Onboarding.storyboard

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="fde-UX-327">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="fde-UX-327">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -59,7 +59,11 @@ DQ
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kbp-ED-vvP">
<rect key="frame" x="14" y="13" width="70" height="32"/>
<rect key="frame" x="14" y="-1" width="62" height="61"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="nfD-s1-MfF"/>
<constraint firstAttribute="width" constant="50" id="opl-FH-00w"/>
</constraints>
<buttonCell key="cell" type="push" title="Back" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Tfk-vV-OpF">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -82,9 +86,9 @@ DQ
<constraints>
<constraint firstItem="1Ko-An-hua" firstAttribute="top" secondItem="Ni6-PX-phh" secondAttribute="top" id="2bT-se-1u6"/>
<constraint firstItem="W3z-nZ-e6B" firstAttribute="centerY" secondItem="m1D-bY-RlD" secondAttribute="centerY" id="400-89-NtL"/>
<constraint firstItem="kbp-ED-vvP" firstAttribute="centerY" secondItem="W3z-nZ-e6B" secondAttribute="centerY" id="ME8-1n-gwM"/>
<constraint firstItem="m1D-bY-RlD" firstAttribute="leading" secondItem="W3z-nZ-e6B" secondAttribute="trailing" constant="12" id="Qhg-jE-HhD"/>
<constraint firstAttribute="bottom" secondItem="m1D-bY-RlD" secondAttribute="bottom" constant="20" id="fOA-We-eTK"/>
<constraint firstAttribute="bottom" secondItem="kbp-ED-vvP" secondAttribute="bottom" constant="20" id="iLS-LX-tVr"/>
<constraint firstAttribute="trailing" secondItem="1Ko-An-hua" secondAttribute="trailing" id="isv-7Q-mq8"/>
<constraint firstItem="kbp-ED-vvP" firstAttribute="leading" secondItem="Ni6-PX-phh" secondAttribute="leading" constant="20" id="mL5-Rp-ka8"/>
<constraint firstItem="1Ko-An-hua" firstAttribute="leading" secondItem="Ni6-PX-phh" secondAttribute="leading" id="s1T-x1-7ww"/>
@ -421,7 +425,7 @@ DQ
<objects>
<viewController storyboardIdentifier="onboardingSearchVC" id="bMm-q2-fpd" customClass="OnboardingSearchController" customModule="Clocker" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="r3Q-VK-VHF">
<rect key="frame" x="0.0" y="0.0" width="436" height="387"/>
<rect key="frame" x="0.0" y="0.0" width="465" height="387"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="16a-9S-3hj">
@ -433,7 +437,7 @@ DQ
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ClockerIcon-512" id="bjq-tD-CZ4"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2ra-RP-SYR">
<rect key="frame" x="120" y="311" width="94" height="16"/>
<rect key="frame" x="120" y="304" width="94" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" placeholderString="Onboarding Info" id="SIV-aM-Wjg">
<font key="font" size="12" name="Avenir-Book"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -441,7 +445,7 @@ DQ
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hqW-RG-UOt">
<rect key="frame" x="118" y="322" width="203" height="45"/>
<rect key="frame" x="118" y="315" width="203" height="45"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" placeholderString="Screen Name" id="QDu-mo-gtb">
<font key="font" size="33" name="Avenir-Book"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -449,7 +453,7 @@ DQ
</textFieldCell>
</textField>
<searchField wantsLayer="YES" verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2w-fr-zQp" customClass="ClockerSearchField" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="20" y="235" width="396" height="22"/>
<rect key="frame" x="20" y="235" width="425" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="7wX-F5-PaV"/>
</constraints>
@ -461,19 +465,19 @@ DQ
<accessibility identifier="searchField"/>
</searchField>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="35" horizontalPageScroll="10" verticalLineScroll="35" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RGd-Ev-FdZ">
<rect key="frame" x="20" y="49" width="396" height="160"/>
<rect key="frame" x="20" y="49" width="425" height="160"/>
<clipView key="contentView" ambiguous="YES" id="XpR-1t-AQy">
<rect key="frame" x="0.0" y="0.0" width="396" height="160"/>
<rect key="frame" x="0.0" y="0.0" width="425" height="160"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="33" rowSizeStyle="automatic" viewBased="YES" id="30y-X6-i7I">
<rect key="frame" x="0.0" y="0.0" width="396" height="160"/>
<rect key="frame" x="0.0" y="0.0" width="425" height="160"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="393" minWidth="40" maxWidth="1000" id="2gZ-a7-gsB">
<tableColumn width="384" minWidth="40" maxWidth="1000" id="2gZ-a7-gsB">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -486,7 +490,7 @@ DQ
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="resultHeaderCellView" misplaced="YES" id="58e-cL-Nln" customClass="ResultSectionHeaderTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="1" width="393" height="23"/>
<rect key="frame" x="1" y="1" width="384" height="23"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="ceH-HF-rVw">
@ -509,11 +513,11 @@ DQ
</connections>
</tableCellView>
<tableCellView identifier="resultCellView" misplaced="YES" id="Et0-Ex-6mu" customClass="ResultTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="26" width="393" height="33"/>
<rect key="frame" x="1" y="26" width="384" height="33"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="73t-th-Wh0">
<rect key="frame" x="-2" y="0.0" width="392" height="27"/>
<rect key="frame" x="-2" y="0.0" width="383" height="27"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="left" title="Search Result Name" placeholderString="Search Result Name" id="gDs-r6-Az3">
<font key="font" size="20" name="Avenir-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -541,7 +545,7 @@ DQ
<constraint firstAttribute="height" constant="160" id="6LG-0s-4fF"/>
</constraints>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="AJ2-lA-FnL">
<rect key="frame" x="0.0" y="124" width="396" height="16"/>
<rect key="frame" x="0.0" y="144" width="396" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="gRQ-Ow-yOF">
@ -558,7 +562,7 @@ DQ
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="51r-DX-fZU">
<rect key="frame" x="22" y="30" width="394" height="16"/>
<rect key="frame" x="22" y="30" width="423" height="16"/>
<buttonCell key="cell" type="bevel" title="UNDO" bezelStyle="rounded" alignment="left" imageScaling="proportionallyDown" inset="2" id="h5W-mQ-yIP">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="12" name="Avenir-Medium"/>
@ -569,22 +573,17 @@ DQ
</button>
</subviews>
<constraints>
<constraint firstItem="wDx-nO-z0M" firstAttribute="top" secondItem="30y-X6-i7I" secondAttribute="bottom" constant="2" id="4og-pY-dHR"/>
<constraint firstItem="2ra-RP-SYR" firstAttribute="leading" secondItem="hqW-RG-UOt" secondAttribute="leading" constant="2" id="7mH-Ln-u0a"/>
<constraint firstItem="16a-9S-3hj" firstAttribute="leading" secondItem="r3Q-VK-VHF" secondAttribute="leading" constant="20" id="9fu-69-cfH"/>
<constraint firstItem="RGd-Ev-FdZ" firstAttribute="leading" secondItem="r3Q-VK-VHF" secondAttribute="leading" constant="20" id="ApV-Wr-6Gy"/>
<constraint firstItem="D2w-fr-zQp" firstAttribute="top" secondItem="16a-9S-3hj" secondAttribute="bottom" constant="30" id="Hmb-4J-wVF"/>
<constraint firstItem="2ra-RP-SYR" firstAttribute="top" secondItem="hqW-RG-UOt" secondAttribute="bottom" constant="-5" id="N5D-cY-fuJ"/>
<constraint firstItem="RGd-Ev-FdZ" firstAttribute="top" secondItem="D2w-fr-zQp" secondAttribute="bottom" constant="26" id="Un4-zl-ZCZ"/>
<constraint firstItem="hqW-RG-UOt" firstAttribute="centerY" secondItem="16a-9S-3hj" secondAttribute="centerY" constant="-10" id="Z0R-lN-mSQ"/>
<constraint firstItem="D2w-fr-zQp" firstAttribute="leading" secondItem="r3Q-VK-VHF" secondAttribute="leading" constant="20" id="fut-DD-1Uj"/>
<constraint firstAttribute="trailing" secondItem="D2w-fr-zQp" secondAttribute="trailing" constant="20" id="g4d-q3-JXg"/>
<constraint firstAttribute="trailing" secondItem="51r-DX-fZU" secondAttribute="trailing" constant="20" id="ixH-7I-UQ5"/>
<constraint firstItem="wDx-nO-z0M" firstAttribute="leading" secondItem="r3Q-VK-VHF" secondAttribute="leading" constant="22" id="kbZ-Gb-IFo"/>
<constraint firstItem="51r-DX-fZU" firstAttribute="centerY" secondItem="wDx-nO-z0M" secondAttribute="centerY" id="nPE-UG-l8T"/>
<constraint firstItem="16a-9S-3hj" firstAttribute="top" secondItem="r3Q-VK-VHF" secondAttribute="top" constant="20" id="p9J-gq-Fqy"/>
<constraint firstItem="hqW-RG-UOt" firstAttribute="top" secondItem="16a-9S-3hj" secondAttribute="top" id="sQX-el-0aw"/>
<constraint firstAttribute="trailing" secondItem="RGd-Ev-FdZ" secondAttribute="trailing" constant="20" id="sSL-Ae-eYf"/>
<constraint firstItem="51r-DX-fZU" firstAttribute="leading" secondItem="wDx-nO-z0M" secondAttribute="trailing" id="waW-dn-Plp"/>
<constraint firstItem="hqW-RG-UOt" firstAttribute="leading" secondItem="16a-9S-3hj" secondAttribute="trailing" constant="20" id="yQc-Ub-zMT"/>
</constraints>
</view>
@ -599,7 +598,7 @@ DQ
</viewController>
<customObject id="VtX-cF-vU0" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1984.5" y="749.5"/>
<point key="canvasLocation" x="1984" y="749.5"/>
</scene>
<!--Final Onboarding View Controller-->
<scene sceneID="5L4-Km-YMW">

11
Clocker/Onboarding/OnboardingParentViewController.swift

@ -63,12 +63,19 @@ class OnboardingParentViewController: NSViewController {
positiveButton.title = NSLocalizedString("Get Started",
comment: "Title for Welcome View Controller's Continue Button")
backButton.title = NSLocalizedString("Back",
comment: "Button title for going back to the previous screen")
positiveButton.tag = OnboardingType.welcome.rawValue
backButton.tag = OnboardingType.welcome.rawValue
[negativeButton, backButton].forEach { $0?.isHidden = true }
if #available(OSX 10.16, *) {
// negativeButton.controlSize = .large
// positiveButton.controlSize = .large
backButton.image = Themer.shared().symbolImage(for: "chevron.left.circle.fill", "back-button")
} else {
backButton.title = NSLocalizedString("Back",
comment: "Button title for going back to the previous screen")
}
}
private func setIdentifiersForTests() {

33
Clocker/Overall App/Themer.swift

@ -151,6 +151,10 @@ extension Themer {
}
func shutdownImage() -> NSImage {
if #available(macOS 10.16, *) {
return symbolImage(for: "ellipsis.circle", nil)
}
if #available(macOS 10.14, *) {
switch themeIndex {
case .light:
@ -166,6 +170,10 @@ extension Themer {
}
func preferenceImage() -> NSImage {
if #available(macOS 10.16, *) {
return symbolImage(for: "gear", nil)
}
if #available(macOS 10.14, *) {
switch themeIndex {
case .light:
@ -177,10 +185,17 @@ extension Themer {
}
}
return themeIndex == .light ? NSImage(named: NSImage.Name("Settings"))! : NSImage(named: NSImage.Name("Settings-White"))!
return
themeIndex == .light
? NSImage(named: NSImage.Name("Settings"))!
: NSImage(named: NSImage.Name("Settings-White"))!
}
func pinImage() -> NSImage {
if #available(macOS 10.16, *) {
return symbolImage(for: "macwindow.on.rectangle", nil)
}
if #available(macOS 10.14, *) {
switch themeIndex {
case .light:
@ -192,7 +207,9 @@ extension Themer {
}
}
return themeIndex == .light ? NSImage(named: NSImage.Name("Float"))! : NSImage(named: NSImage.Name("Float-White"))!
return themeIndex == .light
? NSImage(named: NSImage.Name("Float"))!
: NSImage(named: NSImage.Name("Float-White"))!
}
func sunriseImage() -> NSImage {
@ -299,6 +316,10 @@ extension Themer {
}
func sharingImage() -> NSImage {
if #available(macOS 10.16, *) {
return symbolImage(for: "square.and.arrow.up.on.square.fill", nil)
}
if #available(macOS 10.14, *) {
switch themeIndex {
case .light:
@ -306,7 +327,7 @@ extension Themer {
case .dark:
return NSImage(named: NSImage.Name("SharingDarkIcon"))!
case .system:
return NSImage(named: NSImage.shareTemplateName)!
return NSImage(named: NSImage.Name("Sharing Dynamic"))!
}
}
@ -423,4 +444,10 @@ extension Themer {
NSColor(deviceRed: 241.0 / 255.0, green: 241.0 / 255.0, blue: 241.0 / 255.0, alpha: 1.0) :
NSColor(deviceRed: 42.0 / 255.0, green: 55.0 / 255.0, blue: 62.0 / 255.0, alpha: 1.0)
}
func symbolImage(for _: String, _: String?) -> NSImage {
// Dummy image for older xcodes
return NSImage(named: NSImage.Name("Calendar Tab Icon"))!
// return NSImage(systemSymbolName: name, accessibilityDescription: accessibilityDescription)!
}
}

257
Clocker/Overall App/VersionUpdateHandler.swift

@ -15,6 +15,11 @@ class VersionUpdateHandler: NSObject {
static let kMacRequestTimeout: Double = 60.0
static let kVersionCheckLastVersionKey = "VersionCheckLastVersionKey"
static let kVersionIgnoreVersionKey = "VersionCheckIgnoreVersionKey"
static let kMacAppStoreIDKey = "VersionCheckAppStoreIDKey"
static let kVersionLastCheckedKey = "VersionLastCheckedKey"
static let kVersionLastRemindedKey = "VersionLastRemindedKey"
static let sharedInstance = VersionUpdateHandler()
private var appStoreCountry: String!
private var applicationVersion: String!
@ -26,6 +31,10 @@ class VersionUpdateHandler: NSObject {
private var checkPeriod: Float = 0.0
private var remindPeriod: Float = 1.0
private var verboseLogging: Bool = true
private var updateURL: URL!
private var checkingForNewVersion: Bool = false
private var remoteVersionsDict: [String: Any] = [:]
private var downloadError: Error?
private var showOnFirstLaunch: Bool = false
public var previewMode: Bool = false
@ -53,24 +62,98 @@ class VersionUpdateHandler: NSObject {
super.init()
}
private func shouldCheckForNewVersion() -> Bool {
return true
private func inThisVersionTitle() -> String {
return "New in this version"
}
private func applicationLaunched() {
if checkAtLaunch {
checkIfNewVersion()
} else if verboseLogging {
print("iVersion will not check for updatess because checkAtLaunch option is disabled")
private func updateAvailableTitle() -> String {
return "New version available"
}
private func versionLabelFormat() -> String {
return "Version %@"
}
private func okayButtonLabel() -> String {
return "OK"
}
private func ignoreButtonLabel() -> String {
return "Ignore"
}
private func downloadButtonLabel() -> String {
return "Download"
}
private func remindButtonLabel() -> String {
return "Remind Me Later"
}
private func updatedURL() -> URL {
if updateURL.absoluteString.count > 0 {
return updateURL
}
guard let appStoreId = appStoreID() else {
print("No App Store ID was found for Clocker")
return URL(string: "")!
}
return URL(string: "macappstore://itunes.apple.com/app/id\(appStoreId)")!
}
private func appStoreID() -> Int? {
return UserDefaults.standard.integer(forKey: VersionUpdateHandler.kMacAppStoreIDKey)
}
func setAppStoreID(_ appStoreID: Int) {
UserDefaults.standard.set(appStoreID, forKey: VersionUpdateHandler.kMacAppStoreIDKey)
}
private func setLastChecked(_ date: Date) {
UserDefaults.standard.set(date, forKey: VersionUpdateHandler.kVersionLastCheckedKey)
}
private func lastChecked() -> Date? {
return UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionLastCheckedKey) as? Date
}
private func setLastReminded(_ date: Date?) {
UserDefaults.standard.set(date, forKey: VersionUpdateHandler.kVersionLastRemindedKey)
}
private func lastReminded() -> Date? {
return UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionLastRemindedKey) as? Date
}
private func ignoredVersion() -> String? {
return UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionIgnoreVersionKey) as? String
}
private func setIgnoredVersion(_ version: String) {
UserDefaults.standard.set(version, forKey: VersionUpdateHandler.kVersionIgnoreVersionKey)
}
private func setViewedVersionDetails(_ viewed: Bool) {
UserDefaults.standard.set(viewed ? applicationVersion : nil, forKey: VersionUpdateHandler.kVersionCheckLastVersionKey)
}
private func viewedVersionDetails() -> Bool {
let lastVersionKey = UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionCheckLastVersionKey) as? String ?? ""
return lastVersionKey == applicationVersion
}
private func lastVersion() -> String {
return UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionCheckLastVersionKey) as? String ?? ""
}
private func setLastReminded(_ date: Date?) {
UserDefaults.standard.set(date, forKey: VersionUpdateHandler.kVersionIgnoreVersionKey)
private func setLastVersion(_ version: String) {
UserDefaults.standard.set(version, forKey: VersionUpdateHandler.kVersionCheckLastVersionKey)
}
private func localVersionsDict() -> [String: Any] {
return [String: Any]()
}
private func versionDetails(_ version: String, _ dict: [String: Any]) -> String? {
@ -82,17 +165,40 @@ class VersionUpdateHandler: NSObject {
return nil
}
private func setViewedVersionDetails(_ viewed: Bool) {
UserDefaults.standard.set(viewed ? applicationVersion : nil, forKey: VersionUpdateHandler.kVersionCheckLastVersionKey)
private func versionDetails(since lastVersion: String, in dict: [String: Any]) -> String? {
var lastVersionCopy = lastVersion
if previewMode {
lastVersionCopy = "0"
}
var newVersionFound = false
var details: String = ""
let versions = dict.keys.sorted()
for version in versions {
if version.compareVersion(lastVersionCopy) == .orderedDescending {
newVersionFound = true
}
details.append(versionDetails(version, dict) ?? "")
details.append("\n")
}
if newVersionFound {
return details.trimmingCharacters(in: CharacterSet.newlines)
}
return nil
}
private func viewedVersionDetails() -> Bool {
let lastVersionKey = UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionCheckLastVersionKey) as? String ?? ""
return lastVersionKey == applicationVersion
private func shouldCheckForNewVersion() -> Bool {
return true
}
private func localVersionsDict() -> [String: Any] {
return [String: Any]()
private func applicationLaunched() {
if checkAtLaunch {
checkIfNewVersion()
} else if verboseLogging {
print("iVersion will not check for updatess because checkAtLaunch option is disabled")
}
}
private func versionDetailsString() -> String {
@ -101,12 +207,129 @@ class VersionUpdateHandler: NSObject {
versionDetails = versionDetails(applicationVersion, localVersionsDict())
}
} else {
versionDetails = versionDetails(lastVersion(), localVersionsDict())
versionDetails = versionDetails(since: lastVersion(), in: localVersionsDict())
}
return versionDetails!
}
private func mostRecentVersionInDict(_ dict: [String: Any]) -> String {
// return [dictionary.allKeys sortedArrayUsingSelector:@selector(compareVersion:)].lastObject;
// TODO: Fix this sorting
return dict.keys.sorted().last ?? ""
}
private func showAlertWithTitle(_ title: String, _ details: String, _ defaultButton: String, _ ignoreButton: String, _ remindButton: String) -> NSAlert {
let floatMax = CGFloat.greatestFiniteMagnitude
let alert = NSAlert()
alert.messageText = title
alert.informativeText = inThisVersionTitle()
alert.addButton(withTitle: defaultButton)
let scrollView = NSScrollView(frame: NSRect(x: 0.0,
y: 0.0,
width: 380.0,
height: 15.0))
let contentSize = scrollView.contentSize
scrollView.borderType = .bezelBorder
scrollView.hasVerticalScroller = true
scrollView.hasHorizontalScroller = false
scrollView.autoresizingMask = [.width, .height]
let textView = NSTextView(frame: NSRect(x: 0.0,
y: 0.0,
width: contentSize.width,
height: contentSize.height))
textView.minSize = NSMakeSize(0.0, contentSize.height)
textView.maxSize = NSMakeSize(floatMax, floatMax)
textView.isVerticallyResizable = true
textView.isHorizontallyResizable = false
textView.isEditable = false
textView.autoresizingMask = .width
textView.textContainer?.containerSize = NSMakeSize(contentSize.width, floatMax)
textView.textContainer?.widthTracksTextView = true
textView.string = details
scrollView.documentView = textView
textView.sizeToFit()
let height = min(200.0, scrollView.documentView?.frame.size.height ?? 200.0) + 3.0
scrollView.frame = NSMakeRect(0.0, 0.0, scrollView.frame.size.width, height)
alert.accessoryView = scrollView
if ignoreButton.count > 0 {
alert.addButton(withTitle: ignoreButton)
}
if remindButton.count > 0 {
alert.addButton(withTitle: remindButton)
let modalResponse = alert.runModal()
if modalResponse == .alertFirstButtonReturn {
// Right most button
didDismissAlert(alert, 0)
} else if modalResponse == .alertSecondButtonReturn {
didDismissAlert(alert, 1)
} else {
didDismissAlert(alert, 2)
}
}
return alert
}
private func showIgnoreButton() -> Bool {
return false
}
private func showRemindButtton() -> Bool {
return false
}
private func didDismissAlert(_: NSAlert, _: Int) {
// Get Button Indice
}
private func downloadVersionsData() {
if onlyPromptIfMainWindowIsAvailable {
guard NSApplication.shared.mainWindow != nil else {
return
}
_ = Repeater(interval: .seconds(0.5), mode: .infinite) { _ in
OperationQueue.main.addOperation { [weak self] in
guard let self = self else {
return
}
self.downloadVersionsData()
}
}
}
if checkingForNewVersion {
checkingForNewVersion = false
if remoteVersionsDict.count <= 0 {
if downloadError != nil {
print("Update Check Failed because of \(downloadError!.localizedDescription)")
} else {
print("Version Update Check because an unknown error occurred")
}
}
return
}
let details = versionDetails(since: applicationVersion, in: remoteVersionsDict)
let mostRecentVersion = mostRecentVersionInDict(remoteVersionsDict)
if details != nil {
// Check if ignored
let showDetails = ignoredVersion() == mostRecentVersion || previewMode
if showDetails {}
}
}
private func checkIfNewVersion() {
if onlyPromptIfMainWindowIsAvailable {
guard NSApplication.shared.mainWindow != nil else {

26
Clocker/Panel/Data Layer/TimezoneDataOperations.swift

@ -33,6 +33,32 @@ extension TimezoneDataOperations {
return dateFormatter.string(from: newDate)
}
private func checkForUpcomingEvents() -> (String, String)? {
if DataStore.shared().shouldDisplay(.showMeetingInMenubar) {
let filteredDates = EventCenter.sharedCenter().eventsForDate
let autoupdatingCal = EventCenter.sharedCenter().autoupdatingCalendar
guard let events = filteredDates[autoupdatingCal.startOfDay(for: Date())] else {
return nil
}
for event in events {
if event.event.startDate.timeIntervalSinceNow > 0, !event.isAllDay {
let timeForEventToStart = event.event.startDate.timeIntervalSinceNow / 60
if timeForEventToStart > 30 {
print("Our next event: \(event.event.title ?? "Error") starts in \(timeForEventToStart) mins")
continue
}
return EventCenter.sharedCenter().separateFormat(event: event.event)
}
}
}
return nil
}
func compactMenuTitle() -> String {
var subtitle = CLEmptyString

4
Clocker/Panel/Notes Popover/NotesPopover.swift

@ -75,6 +75,10 @@ class NotesPopover: NSViewController {
setReminderCheckbox.setAccessibilityIdentifier("ReminderCheckbox")
alertPopupButton.setAccessibilityIdentifier("RemindersAlertPopup")
reminderView.setAccessibilityIdentifier("RemindersView")
if #available(macOS 10.16, *) {
alertPopupButton.controlSize = .large
}
}
override func viewWillAppear() {

25
Clocker/Panel/Notes Popover/NotesPopover.xib

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17132" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17132"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -87,7 +87,7 @@
<constraint firstAttribute="height" constant="22" id="wGh-4g-gQ3"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="CUSTOMIZE" id="AWQ-XX-6Ai">
<font key="font" metaFont="toolTip"/>
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -187,7 +187,7 @@
<rect key="frame" x="0.0" y="137" width="300" height="60"/>
<subviews>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="seL-7y-MOc">
<rect key="frame" x="18" y="10" width="265" height="24"/>
<rect key="frame" x="18" y="11" width="265" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="Low-Q8-K5h">
<font key="font" size="12" name="Avenir-Book"/>
<segments>
@ -201,9 +201,9 @@
</connections>
</segmentedControl>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wqz-cF-lhm">
<rect key="frame" x="18" y="35" width="274" height="14"/>
<rect key="frame" x="18" y="36" width="274" height="14"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="Timezone Format" id="JnF-g8-GLM">
<font key="font" metaFont="toolTip"/>
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -224,7 +224,7 @@
<rect key="frame" x="0.0" y="77" width="300" height="60"/>
<subviews>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="eiB-dp-56X">
<rect key="frame" x="18" y="10" width="265" height="24"/>
<rect key="frame" x="18" y="11" width="265" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="E2D-Y2-kok">
<font key="font" size="12" name="Avenir-Book"/>
<segments>
@ -238,9 +238,9 @@
</connections>
</segmentedControl>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WVk-sH-CqF">
<rect key="frame" x="18" y="35" width="274" height="14"/>
<rect key="frame" x="18" y="36" width="274" height="14"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="Display Seconds" id="lCg-ZI-gIk">
<font key="font" metaFont="toolTip"/>
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -324,7 +324,7 @@
</constraints>
</progressIndicator>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9hd-54-hYl">
<rect key="frame" x="103" y="-2" width="132" height="36"/>
<rect key="frame" x="102" y="-2" width="134" height="37"/>
<constraints>
<constraint firstAttribute="height" constant="25" id="8tH-mx-HuL"/>
<constraint firstAttribute="width" constant="120" id="gn2-zr-ZRp"/>
@ -338,7 +338,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qgx-Yf-bP8">
<rect key="frame" x="233" y="-2" width="62" height="36"/>
<rect key="frame" x="232" y="-2" width="64" height="37"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="n5J-f7-aqy"/>
<constraint firstAttribute="height" constant="25" id="oQ5-uv-Gfg"/>
@ -346,9 +346,6 @@
<buttonCell key="cell" type="push" title="Done" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="xa4-rw-FBZ">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="12" name="Avenir-Light"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<accessibility identifier="SaveButton"/>
<connections>

10
Clocker/Panel/PanelController.swift

@ -49,10 +49,6 @@ class PanelController: ParentPanelController {
}
}
override func updateDefaultPreferences() {
super.updateDefaultPreferences()
}
func setFrameTheNewWay(_ rect: NSRect, _ maxX: CGFloat) {
// Calculate window's top left point.
// First, center window under status item.
@ -82,6 +78,12 @@ class PanelController: ParentPanelController {
updateDefaultPreferences()
if DataStore.shared().timezones().isEmpty {
futureSliderView.isHidden = true
} else if futureSliderView.isHidden == DataStore.shared().shouldDisplay(.futureSlider) {
futureSliderView.isHidden = false
}
futureSlider.integerValue = 0
sliderDatePicker.dateValue = Date()

71
Clocker/Panel/ParentPanelController.swift

@ -166,6 +166,10 @@ class ParentPanelController: NSWindowController {
object: nil)
showDebugVersionViewIfNeccesary()
if #available(macOS 10.16, *) {
// mainTableView.style = .fullWidth
}
}
private func showDebugVersionViewIfNeccesary() {
@ -387,6 +391,10 @@ class ParentPanelController: NSWindowController {
newHeight += 8.0
}
if object?.isSystemTimezone == true {
newHeight += 5
}
newHeight += mainTableView.intercellSpacing.height
return newHeight
@ -922,6 +930,69 @@ class ParentPanelController: NSWindowController {
sliderDatePicker.dateValue = Date()
setTimezoneDatasourceSlider(sliderValue: 0)
}
@objc func terminateClocker() {
NSApplication.shared.terminate(nil)
}
@objc func reportIssue() {
feedbackWindow.showWindow(nil)
NSApp.activate(ignoringOtherApps: true)
window?.orderOut(nil)
if let countryCode = Locale.autoupdatingCurrent.regionCode {
let custom: [String: Any] = ["Country": countryCode]
Logger.log(object: custom, for: "Report Issue Opened")
}
}
@objc func openCrowdin() {
guard let localizationURL = URL(string: AboutUsConstants.CrowdInLocalizationLink),
let languageCode = Locale.preferredLanguages.first else { return }
NSWorkspace.shared.open(localizationURL)
// Log this
let custom: [String: Any] = ["Language": languageCode]
Logger.log(object: custom, for: "Opened Localization Link")
}
@objc func rate() {
guard let sourceURL = URL(string: AboutUsConstants.AppStoreLink) else { return }
NSWorkspace.shared.open(sourceURL)
}
@IBAction func showMoreOptions(_ sender: NSButton) {
let menuItem = NSMenu(title: "More Options")
let terminateOption = NSMenuItem(title: "Quit Clocker",
action: #selector(terminateClocker), keyEquivalent: "")
let rateClocker = NSMenuItem(title: "Support Clocker...",
action: #selector(rate), keyEquivalent: "")
let sendFeedback = NSMenuItem(title: "Send Feedback...",
action: #selector(reportIssue), keyEquivalent: "")
let localizeClocker = NSMenuItem(title: "Localize Clocker...",
action: #selector(openCrowdin), keyEquivalent: "")
let appDisplayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") ?? "Clocker"
let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "N/A"
let longVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "N/A"
let versionInfo = "\(appDisplayName) \(shortVersion) (\(longVersion))"
let clockerVersionInfo = NSMenuItem(title: versionInfo, action: nil, keyEquivalent: "")
clockerVersionInfo.isEnabled = false
menuItem.addItem(rateClocker)
menuItem.addItem(sendFeedback)
menuItem.addItem(localizeClocker)
menuItem.addItem(NSMenuItem.separator())
menuItem.addItem(clockerVersionInfo)
menuItem.addItem(NSMenuItem.separator())
menuItem.addItem(terminateOption)
NSMenu.popUpContextMenu(menuItem,
with: NSApp.currentEvent!,
for: sender)
}
}
extension ParentPanelController: NSPopoverDelegate {

65
Clocker/Panel/UI/FloatingWindow.xib

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17132" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17132"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -37,30 +37,30 @@
<windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES" ignoresCycle="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="1000" y="379" width="350" height="460"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1025"/>
<value key="minSize" type="size" width="150" height="50"/>
<value key="maxSize" type="size" width="350" height="800"/>
<view key="contentView" id="qEx-SC-5Qd">
<view key="contentView" misplaced="YES" id="qEx-SC-5Qd">
<rect key="frame" x="0.0" y="0.0" width="350" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView focusRingType="none" distribution="fill" orientation="vertical" alignment="leading" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Bn4-fy-Lm6">
<rect key="frame" x="0.0" y="0.0" width="350" height="460"/>
<rect key="frame" x="0.0" y="0.0" width="370" height="460"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="81" horizontalPageScroll="10" verticalLineScroll="81" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="khu-OS-PzP">
<rect key="frame" x="0.0" y="195" width="350" height="265"/>
<rect key="frame" x="0.0" y="195" width="370" height="265"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="2rS-3B-A3C">
<rect key="frame" x="0.0" y="0.0" width="350" height="265"/>
<rect key="frame" x="0.0" y="0.0" width="370" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="80" viewBased="YES" id="3js-Fl-DdU" customClass="PanelTableView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="350" height="265"/>
<rect key="frame" x="0.0" y="0.0" width="370" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="1"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="347" minWidth="303" maxWidth="1000" id="009-6N-KRz">
<tableColumn width="338" minWidth="303" maxWidth="1000" id="009-6N-KRz">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -73,7 +73,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="timeZoneCell" id="UES-Eo-BEf" customClass="TimezoneCellView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="0.0" width="347" height="80"/>
<rect key="frame" x="11" y="0.0" width="347" height="80"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="751" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="751" tag="100" preferredMaxLayoutWidth="150" translatesAutoresizingMaskIntoConstraints="NO" id="Nov-Lq-MHq">
@ -139,13 +139,13 @@
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="Sunrise" id="jMh-PW-Exi"/>
</imageView>
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xGh-3b-9zf">
<rect key="frame" x="5" y="1" width="30" height="64"/>
<rect key="frame" x="5" y="4" width="30" height="61"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="k4t-Nn-Fzn">
<rect key="frame" x="3" y="39" width="25" height="25"/>
<rect key="frame" x="4" y="39" width="22" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="25" id="3Xl-5P-qip"/>
<constraint firstAttribute="width" constant="25" id="wef-ia-KFo"/>
<constraint firstAttribute="height" constant="22" id="3Xl-5P-qip"/>
<constraint firstAttribute="width" constant="22" id="wef-ia-KFo"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="CurrentLocation" id="7CP-TW-ZBQ"/>
</imageView>
@ -208,7 +208,7 @@
</connections>
</tableCellView>
<tableCellView identifier="addCell" id="ort-42-Yhe" customClass="AddTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="1" y="81" width="347" height="100"/>
<rect key="frame" x="11" y="81" width="347" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1o3-e8-MQn">
@ -254,7 +254,7 @@
</scroller>
</scrollView>
<customView identifier="Review Cell" translatesAutoresizingMaskIntoConstraints="NO" id="HBv-Eh-z9y">
<rect key="frame" x="0.0" y="145" width="350" height="50"/>
<rect key="frame" x="0.0" y="145" width="370" height="50"/>
<subviews>
<stackView distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" fixedFrame="YES" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Y83-Ew-CDw">
<rect key="frame" x="80" y="30" width="185" height="20"/>
@ -283,7 +283,7 @@
<rect key="frame" x="75" y="4" width="200" height="21"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8oB-ID-Dka">
<rect key="frame" x="-6" y="-7" width="108" height="32"/>
<rect key="frame" x="-7" y="-6" width="110" height="32"/>
<buttonCell key="cell" type="push" title="Yes!" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0tg-Hq-QXV">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="Avenir-Light"/>
@ -293,7 +293,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7ID-ll-0YN">
<rect key="frame" x="98" y="-7" width="108" height="32"/>
<rect key="frame" x="97" y="-7" width="110" height="33"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="H1a-d6-Y0v"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="96" id="yWy-SJ-EE0"/>
@ -323,13 +323,13 @@
<accessibility description="Review Cell"/>
</customView>
<customView wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Z63-pM-8OA" customClass="ReviewView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="70" width="350" height="75"/>
<rect key="frame" x="0.0" y="70" width="370" height="75"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="PpA-GH-1PV" customClass="ClockerTextBackgroundView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="330" height="55"/>
<rect key="frame" x="10" y="10" width="350" height="55"/>
<subviews>
<button focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8q4-YZ-gkb">
<rect key="frame" x="21" y="11" width="269" height="18"/>
<rect key="frame" x="21" y="11" width="289" height="18"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="IIB-zJ-L1u"/>
</constraints>
@ -349,7 +349,7 @@
</constraints>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A9a-aM-BNn">
<rect key="frame" x="21" y="26" width="251" height="24"/>
<rect key="frame" x="21" y="26" width="271" height="24"/>
<constraints>
<constraint firstAttribute="height" constant="24" id="Ted-52-5mp"/>
</constraints>
@ -360,7 +360,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" tag="55" translatesAutoresizingMaskIntoConstraints="NO" id="0xk-Sz-MQU">
<rect key="frame" x="290" y="10" width="35" height="35"/>
<rect key="frame" x="310" y="10" width="35" height="35"/>
<constraints>
<constraint firstAttribute="width" constant="35" id="n4G-W9-0Xp"/>
<constraint firstAttribute="height" constant="35" id="viN-NC-XR0"/>
@ -401,7 +401,7 @@
<rect key="frame" x="0.0" y="40" width="350" height="30"/>
<subviews>
<datePicker focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ngk-LZ-J2y">
<rect key="frame" x="203" y="2" width="137" height="26"/>
<rect key="frame" x="203" y="0.0" width="137" height="23"/>
<datePickerCell key="cell" focusRingType="none" alignment="left" drawsBackground="NO" datePickerStyle="textField" id="fj6-ZG-8ff">
<font key="font" size="13" name="Avenir-Roman"/>
<date key="date" timeIntervalSinceReferenceDate="-595929600">
@ -416,7 +416,7 @@
</connections>
</datePicker>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XQc-HF-TrM">
<rect key="frame" x="7" y="6" width="196" height="19"/>
<rect key="frame" x="7" y="2" width="196" height="23"/>
<constraints>
<constraint firstAttribute="height" constant="15" id="UT0-Yf-jfk"/>
</constraints>
@ -428,9 +428,8 @@
</slider>
</subviews>
<constraints>
<constraint firstItem="Ngk-LZ-J2y" firstAttribute="firstBaseline" secondItem="XQc-HF-TrM" secondAttribute="firstBaseline" id="FhF-Ij-XvK"/>
<constraint firstItem="Ngk-LZ-J2y" firstAttribute="leading" secondItem="XQc-HF-TrM" secondAttribute="trailing" constant="2" id="GZh-tD-ZEU"/>
<constraint firstAttribute="bottom" secondItem="Ngk-LZ-J2y" secondAttribute="bottom" constant="2" id="MBn-Ru-qXi"/>
<constraint firstItem="Ngk-LZ-J2y" firstAttribute="top" secondItem="6vv-g2-Z63" secondAttribute="top" constant="2" id="MTp-Xi-H8s"/>
<constraint firstAttribute="trailing" secondItem="Ngk-LZ-J2y" secondAttribute="trailing" constant="10" id="QMe-St-qSH"/>
<constraint firstAttribute="height" constant="30" id="YVW-Xj-U2r"/>
<constraint firstItem="XQc-HF-TrM" firstAttribute="leading" secondItem="6vv-g2-Z63" secondAttribute="leading" constant="9" id="gvD-R0-ANg"/>
@ -446,13 +445,13 @@
<constraint firstAttribute="height" constant="25" id="Aj8-oI-SG6"/>
<constraint firstAttribute="width" constant="30" id="n8F-JR-9KP"/>
</constraints>
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="PowerIcon" imagePosition="only" alignment="center" alternateImage="PowerIcon" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cXX-25-Pif">
<buttonCell key="cell" type="recessed" bezelStyle="recessed" image="PowerIcon" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cXX-25-Pif">
<behavior key="behavior" lightByContents="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<accessibility identifier="Close"/>
<connections>
<action selector="terminate:" target="-1" id="wej-hC-hIT"/>
<action selector="showMoreOptions:" target="-2" id="k5Z-IW-8DZ"/>
</connections>
</button>
<button toolTip="Switch between Menubar/Floating mode." verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KWj-8n-2K0">
@ -559,10 +558,10 @@
<image name="Add Icon" width="700" height="700"/>
<image name="CurrentLocation" width="350" height="350"/>
<image name="Extra" width="700" height="700"/>
<image name="Float" width="700" height="700"/>
<image name="NSActionTemplate" width="14" height="14"/>
<image name="NSShareTemplate" width="11" height="16"/>
<image name="PowerIcon" width="270" height="270"/>
<image name="Float" width="15" height="13"/>
<image name="NSActionTemplate" width="17" height="15"/>
<image name="NSShareTemplate" width="16" height="15"/>
<image name="PowerIcon" width="350" height="350"/>
<image name="Remove" width="700" height="700"/>
<image name="Sunrise" width="700" height="700"/>
</resources>

12
Clocker/Panel/UI/TimezoneDataSource.swift

@ -62,6 +62,7 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
cellView.noteLabel.toolTip = currentModel.note ?? CLEmptyString
cellView.currentLocationIndicator.isHidden = !currentModel.isSystemTimezone
cellView.time.setAccessibilityIdentifier("ActualTime")
cellView.relativeDate.setAccessibilityIdentifier("RelativeDate")
cellView.layout(with: currentModel)
cellView.setAccessibilityIdentifier(currentModel.formattedTimezoneLabel())
@ -93,6 +94,10 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
rowHeight += userFontSize.intValue + 25
}
if model.isSystemTimezone {
rowHeight += 5
}
rowHeight += (userFontSize.intValue * 2)
return CGFloat(rowHeight)
}
@ -130,7 +135,12 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
})
swipeToDelete.image = NSImage(named: NSImage.Name("Trash"))
if #available(OSX 10.16, *) {
swipeToDelete.image = Themer.shared().symbolImage(for: "trash.fill", "Trash Button")
} else {
swipeToDelete.image = NSImage(named: NSImage.Name("Trash"))
}
return [swipeToDelete]
}

2
Clocker/Preferences/About/AboutViewController.swift

@ -6,7 +6,7 @@ struct AboutUsConstants {
static let AboutUsNibIdentifier = "CLAboutWindows"
static let GitHubURL = "https://github.com/abhishekbanthia/Clocker/?ref=ClockerApp"
static let PayPalURL = "https://paypal.me/abhishekbanthia1712"
static let TwitterLink = "https://twitter.com/n0shake/?ref=ClockerApp"
static let TwitterLink = "https://twitter.com/clocker_support/?ref=ClockerApp"
static let PersonalWebsite = "http://abhishekbanthia.com/?ref=ClockerApp"
static let AppStoreLink = "macappstore://itunes.apple.com/us/app/clocker/id1056643111?action=write-review"
static let CrowdInLocalizationLink = "https://crwd.in/clocker"

84
Clocker/Preferences/App Feedback/AppFeedbackWindow.xib

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -12,10 +12,10 @@
<outlet property="contactBox" destination="JzF-Oq-qhW" id="CUI-1V-SfW"/>
<outlet property="emailField" destination="zlM-Cf-OxV" id="uRw-dZ-JGR"/>
<outlet property="feedbackTextView" destination="sCg-gV-TTr" id="Evh-WS-epn"/>
<outlet property="headerLabel" destination="gej-YH-9dt" id="mgE-2k-ioK"/>
<outlet property="informativeText" destination="W3a-Hi-ryk" id="qhv-iC-svS"/>
<outlet property="nameField" destination="Qzm-kE-Igl" id="miJ-7A-VPC"/>
<outlet property="progressIndicator" destination="h17-og-9PU" id="AE2-Gh-DpO"/>
<outlet property="quickCommentsLabel" destination="j4P-EU-Uso" id="TSm-DN-QeM"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
@ -23,24 +23,24 @@
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Clocker Feedback" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="437" y="172" width="319" height="392"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<rect key="contentRect" x="437" y="172" width="319" height="440"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="319" height="392"/>
<rect key="frame" x="0.0" y="0.0" width="319" height="440"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oNX-kV-RGt">
<rect key="frame" x="12" y="205" width="295" height="145"/>
<rect key="frame" x="12" y="230" width="295" height="122"/>
<clipView key="contentView" drawsBackground="NO" id="NNn-eZ-8Je">
<rect key="frame" x="1" y="1" width="293" height="143"/>
<rect key="frame" x="1" y="1" width="293" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="sCg-gV-TTr">
<rect key="frame" x="0.0" y="0.0" width="293" height="143"/>
<rect key="frame" x="0.0" y="0.0" width="293" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="293" height="143"/>
<size key="minSize" width="293" height="120"/>
<size key="maxSize" width="463" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
</textView>
@ -55,14 +55,14 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<box boxType="custom" borderType="line" title="Box Title" translatesAutoresizingMaskIntoConstraints="NO" id="JzF-Oq-qhW">
<rect key="frame" x="12" y="67" width="295" height="125"/>
<box translatesAutoresizingMaskIntoConstraints="NO" id="JzF-Oq-qhW">
<rect key="frame" x="9" y="63" width="301" height="154"/>
<view key="contentView" id="moX-Vc-vMc">
<rect key="frame" x="1" y="1" width="293" height="123"/>
<rect key="frame" x="3" y="3" width="295" height="135"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" preferredMaxLayoutWidth="269" translatesAutoresizingMaskIntoConstraints="NO" id="Qzm-kE-Igl">
<rect key="frame" x="10" y="88" width="273" height="24"/>
<rect key="frame" x="10" y="100" width="275" height="24"/>
<constraints>
<constraint firstAttribute="height" constant="24" id="6DY-uj-pMG"/>
</constraints>
@ -73,7 +73,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" preferredMaxLayoutWidth="269" translatesAutoresizingMaskIntoConstraints="NO" id="zlM-Cf-OxV">
<rect key="frame" x="10" y="54" width="266" height="24"/>
<rect key="frame" x="10" y="66" width="267" height="24"/>
<constraints>
<constraint firstAttribute="height" constant="24" id="b3M-Sc-y8S"/>
</constraints>
@ -84,7 +84,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" preferredMaxLayoutWidth="269" translatesAutoresizingMaskIntoConstraints="NO" id="LVY-Qw-MYC">
<rect key="frame" x="6" y="0.0" width="281" height="44"/>
<rect key="frame" x="6" y="0.0" width="283" height="56"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" placeholderString="Accessory Info" id="yEq-6I-HBq">
<font key="font" size="10" name="Avenir-Book"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -98,6 +98,7 @@
<constraint firstItem="Qzm-kE-Igl" firstAttribute="top" secondItem="moX-Vc-vMc" secondAttribute="top" constant="11" id="Dpz-4F-hN7"/>
<constraint firstItem="Qzm-kE-Igl" firstAttribute="leading" secondItem="moX-Vc-vMc" secondAttribute="leading" constant="10" id="GKZ-24-t7t"/>
<constraint firstItem="LVY-Qw-MYC" firstAttribute="top" secondItem="zlM-Cf-OxV" secondAttribute="bottom" constant="10" id="Xck-iy-cZk"/>
<constraint firstAttribute="trailing" secondItem="LVY-Qw-MYC" secondAttribute="trailing" constant="8" id="b5X-pR-y2N"/>
<constraint firstItem="LVY-Qw-MYC" firstAttribute="leading" secondItem="moX-Vc-vMc" secondAttribute="leading" constant="8" id="iLs-Ob-MZC"/>
<constraint firstItem="LVY-Qw-MYC" firstAttribute="centerX" secondItem="moX-Vc-vMc" secondAttribute="centerX" id="k3n-00-eiV"/>
<constraint firstAttribute="bottom" secondItem="LVY-Qw-MYC" secondAttribute="bottom" id="p1w-eh-TeV"/>
@ -105,7 +106,7 @@
</constraints>
</view>
<constraints>
<constraint firstAttribute="height" constant="125" id="lwa-Yt-uxh"/>
<constraint firstAttribute="height" constant="150" id="lwa-Yt-uxh"/>
</constraints>
<font key="titleFont" size="11" name="Avenir-Book"/>
</box>
@ -143,17 +144,6 @@ DQ
<action selector="sendFeedback:" target="-2" id="lrL-0l-Jbd"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gej-YH-9dt">
<rect key="frame" x="10" y="358" width="299" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="a7O-DC-irX"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" placeholderString="Header Text" id="oHe-hu-bQn">
<font key="font" size="13" name="Avenir-Book"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="W3a-Hi-ryk">
<rect key="frame" x="10" y="47" width="289" height="22"/>
<constraints>
@ -168,6 +158,36 @@ DQ
<progressIndicator wantsLayer="YES" maxValue="100" indeterminate="YES" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="h17-og-9PU">
<rect key="frame" x="12" y="19" width="79" height="20"/>
</progressIndicator>
<box translatesAutoresizingMaskIntoConstraints="NO" id="bGc-DH-2iw">
<rect key="frame" x="9" y="356" width="301" height="84"/>
<view key="contentView" id="6oZ-b5-xPJ">
<rect key="frame" x="3" y="3" width="295" height="65"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="j4P-EU-Uso" customClass="UnderlinedButton" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="5" y="25" width="285" height="15"/>
<buttonCell key="cell" type="bevel" title="Quick Comments Button" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="FQy-Mb-DcS">
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
<font key="font" size="11" name="Avenir-Light"/>
</buttonCell>
<accessibility identifier="ClockerOpenSourceText"/>
<connections>
<action selector="navigateToSupportTwitter:" target="-2" id="kr0-Ks-qua"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="j4P-EU-Uso" firstAttribute="centerX" secondItem="6oZ-b5-xPJ" secondAttribute="centerX" id="Lzk-D8-sUJ"/>
<constraint firstItem="j4P-EU-Uso" firstAttribute="centerY" secondItem="6oZ-b5-xPJ" secondAttribute="centerY" id="Zio-We-YXV"/>
<constraint firstAttribute="trailing" secondItem="j4P-EU-Uso" secondAttribute="trailing" constant="5" id="geY-fl-hwn"/>
<constraint firstItem="j4P-EU-Uso" firstAttribute="leading" secondItem="6oZ-b5-xPJ" secondAttribute="leading" constant="5" id="ilm-9x-zlx"/>
</constraints>
</view>
<constraints>
<constraint firstAttribute="height" constant="80" id="9IW-uw-ubx"/>
</constraints>
<font key="titleFont" size="11" name="Avenir-Light"/>
</box>
</subviews>
<constraints>
<constraint firstItem="JzF-Oq-qhW" firstAttribute="trailing" secondItem="oNX-kV-RGt" secondAttribute="trailing" id="4Vq-PW-upG"/>
@ -175,22 +195,22 @@ DQ
<constraint firstAttribute="trailing" secondItem="zlM-Cf-OxV" secondAttribute="trailing" constant="30" id="Arj-b2-oje"/>
<constraint firstItem="sJq-1o-Bft" firstAttribute="top" secondItem="JzF-Oq-qhW" secondAttribute="bottom" constant="26" id="Epm-On-lNy"/>
<constraint firstAttribute="trailing" secondItem="oNX-kV-RGt" secondAttribute="trailing" constant="12" id="IqR-EG-ga3"/>
<constraint firstItem="bGc-DH-2iw" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="12" id="JMO-BF-p3W"/>
<constraint firstItem="sJq-1o-Bft" firstAttribute="leading" secondItem="szs-8j-SMN" secondAttribute="trailing" constant="8" id="JSB-K6-cbX"/>
<constraint firstAttribute="trailing" secondItem="sJq-1o-Bft" secondAttribute="trailing" constant="20" id="KuW-ez-Od9"/>
<constraint firstItem="JzF-Oq-qhW" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="12" id="NCF-RW-EvZ"/>
<constraint firstAttribute="bottom" secondItem="h17-og-9PU" secondAttribute="bottom" constant="20" id="OLS-kL-muQ"/>
<constraint firstItem="oNX-kV-RGt" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="12" id="P0X-Hb-ZtS"/>
<constraint firstItem="szs-8j-SMN" firstAttribute="leading" secondItem="h17-og-9PU" secondAttribute="trailing" constant="8" id="S7a-To-K83"/>
<constraint firstAttribute="trailing" secondItem="bGc-DH-2iw" secondAttribute="trailing" constant="12" id="Swh-0I-anu"/>
<constraint firstAttribute="bottom" secondItem="sJq-1o-Bft" secondAttribute="bottom" constant="20" id="cft-qs-VMz"/>
<constraint firstItem="oNX-kV-RGt" firstAttribute="top" secondItem="6oZ-b5-xPJ" secondAttribute="bottom" constant="7" id="dlq-R6-ar3"/>
<constraint firstItem="h17-og-9PU" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="12" id="iIH-oN-lBO"/>
<constraint firstAttribute="trailing" secondItem="W3a-Hi-ryk" secondAttribute="trailing" constant="22" id="j6H-0M-Cux"/>
<constraint firstAttribute="trailing" secondItem="gej-YH-9dt" secondAttribute="trailing" constant="12" id="qjH-ND-NKx"/>
<constraint firstItem="gej-YH-9dt" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="12" id="tlA-wq-Gts"/>
<constraint firstItem="bGc-DH-2iw" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="o8t-tV-qS6"/>
<constraint firstItem="JzF-Oq-qhW" firstAttribute="top" secondItem="oNX-kV-RGt" secondAttribute="bottom" constant="13" id="v2l-OZ-epC"/>
<constraint firstItem="szs-8j-SMN" firstAttribute="top" secondItem="W3a-Hi-ryk" secondAttribute="bottom" constant="6" id="vlm-Yj-d84"/>
<constraint firstAttribute="bottom" secondItem="szs-8j-SMN" secondAttribute="bottom" constant="20" id="xos-N8-d1k"/>
<constraint firstItem="gej-YH-9dt" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="14" id="yZE-PY-8EZ"/>
<constraint firstItem="oNX-kV-RGt" firstAttribute="top" secondItem="gej-YH-9dt" secondAttribute="bottom" constant="8" id="yec-Eo-Jb9"/>
</constraints>
</view>
<connections>

43
Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift

@ -33,6 +33,7 @@ class AppFeedbackWindowController: NSWindowController {
@IBOutlet var informativeText: NSTextField!
@IBOutlet var progressIndicator: NSProgressIndicator!
@IBOutlet var quickCommentsLabel: UnderlinedButton!
private var themeDidChangeNotification: NSObjectProtocol?
private var serialNumber: String? {
let platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))
@ -72,6 +73,7 @@ class AppFeedbackWindowController: NSWindowController {
nameField.setAccessibilityIdentifier("NameField")
emailField.setAccessibilityIdentifier("EmailField")
progressIndicator.setAccessibilityIdentifier("ProgressIndicator")
quickCommentsLabel.setAccessibility("QuickCommentLabel")
setup()
@ -204,19 +206,54 @@ class AppFeedbackWindowController: NSWindowController {
informativeText.stringValue = CLEmptyString
}
@IBOutlet var headerLabel: NSTextField!
@IBOutlet var contactBox: NSBox!
@IBOutlet var accessoryInfo: NSTextField!
private func setup() {
headerLabel.stringValue = "Tell us what you think!".localized()
contactBox.title = "Contact Information (Optional)".localized()
accessoryInfo.stringValue = "Contact fields are optional! Your contact information will let us contact you in case we need more information or can help!".localized()
[headerLabel, accessoryInfo].forEach { $0?.textColor = Themer.shared().mainTextColor() }
let range = NSRange(location: 9, length: 15)
quickCommentsLabel.title = "Tweet to @ClockerSupport if you have a quick comment!"
setUnderline(for: quickCommentsLabel, range: range)
[accessoryInfo].forEach { $0?.textColor = Themer.shared().mainTextColor() }
contactBox.borderColor = Themer.shared().mainTextColor()
}
private func setUnderline(for button: UnderlinedButton?, range: NSRange) {
guard let underlinedButton = button else { return }
let mutableParaghStyle = NSMutableParagraphStyle()
mutableParaghStyle.alignment = .center
let originalText = NSMutableAttributedString(string: underlinedButton.title)
originalText.addAttribute(NSAttributedString.Key.underlineStyle,
value: NSNumber(value: Int8(NSUnderlineStyle.single.rawValue)),
range: range)
originalText.addAttribute(NSAttributedString.Key.foregroundColor,
value: Themer.shared().mainTextColor(),
range: NSRange(location: 0, length: underlinedButton.attributedTitle.string.count))
originalText.addAttribute(NSAttributedString.Key.font,
value: (button?.font)!,
range: NSRange(location: 0, length: underlinedButton.attributedTitle.string.count))
originalText.addAttribute(NSAttributedString.Key.paragraphStyle,
value: mutableParaghStyle,
range: NSRange(location: 0, length: underlinedButton.attributedTitle.string.count))
underlinedButton.attributedTitle = originalText
}
@IBAction func navigateToSupportTwitter(_: Any) {
guard let twitterURL = URL(string: AboutUsConstants.TwitterLink),
let countryCode = Locale.autoupdatingCurrent.regionCode else { return }
NSWorkspace.shared.open(twitterURL)
// Log this
let custom: [String: Any] = ["Country": countryCode]
Logger.log(object: custom, for: "Opened Twitter")
}
}
extension AppFeedbackWindowController: NSWindowDelegate {

11
Clocker/Preferences/Calendar/CalendarViewController.swift

@ -81,15 +81,8 @@ class CalendarViewController: ParentViewController {
super.viewWillAppear()
verifyCalendarAccess()
if DataStore.shared().shouldDisplay(ViewType.upcomingEventView) {
showSegmentedControl.selectedSegment = 0
} else {
showSegmentedControl.selectedSegment = 1
}
// If the menubar mode is compact, we can't show meetings in the menubar. So disable toggling that option.
showNextMeetingInMenubarControl.isEnabled = !DataStore.shared().shouldDisplay(.menubarCompactMode)
showSegmentedControl.selectedSegment = DataStore.shared().shouldDisplay(ViewType.upcomingEventView) ? 0 : 1
showNextMeetingInMenubarControl.isEnabled = DataStore.shared().shouldDisplay(.menubarCompactMode) ? false : true
}
private func verifyCalendarAccess() {

15
Clocker/Preferences/OneWindowController.swift

@ -3,21 +3,6 @@
import Cocoa
class CenteredTabViewController: NSTabViewController {
override func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
super.toolbarDefaultItemIdentifiers(toolbar)
var toolbarItems: [NSToolbarItem.Identifier] = [NSToolbarItem.Identifier.flexibleSpace]
tabViewItems.forEach { item in
if let identifier = item.identifier as? String {
toolbarItems.append(NSToolbarItem.Identifier(identifier))
}
}
toolbarItems.append(NSToolbarItem.Identifier.flexibleSpace)
return toolbarItems
}
override func viewDidLoad() {
super.viewDidLoad()

34
Clocker/Preferences/Preferences.storyboard

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="RHq-9Z-auA">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="RHq-9Z-auA">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -1492,7 +1492,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<searchField toolTip="Search a timezone" wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Dha-h9-Nd0" customClass="ClockerSearchField" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="8" y="193" width="329" height="23"/>
<rect key="frame" x="8" y="169" width="329" height="23"/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Enter a city, state, country name" usesSingleLineMode="YES" maximumRecents="5" id="ikU-Tm-0WZ">
<font key="font" size="13" name="Avenir-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -1549,13 +1549,13 @@ DQ
</connections>
</button>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="32" horizontalPageScroll="10" verticalLineScroll="32" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0wY-ff-FLW">
<rect key="frame" x="8" y="30" width="329" height="153"/>
<rect key="frame" x="8" y="30" width="329" height="129"/>
<clipView key="contentView" drawsBackground="NO" id="rGc-3M-cCq">
<rect key="frame" x="0.0" y="0.0" width="329" height="153"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="129"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" rowHeight="30" rowSizeStyle="automatic" viewBased="YES" id="xkl-2X-ZCb">
<rect key="frame" x="0.0" y="0.0" width="329" height="153"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="129"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -1645,14 +1645,14 @@ DQ
</scroller>
</scrollView>
<progressIndicator wantsLayer="YES" focusRingType="none" horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="100" displayedWhenStopped="NO" bezeled="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="0A5-gp-lay">
<rect key="frame" x="165" y="126" width="16" height="16"/>
<rect key="frame" x="165" y="114" width="16" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="fgE-77-Vda"/>
<constraint firstAttribute="width" constant="16" id="pwe-em-e0a"/>
</constraints>
</progressIndicator>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xgb-wU-8RU">
<rect key="frame" x="18" y="96" width="309" height="22"/>
<rect key="frame" x="18" y="84" width="309" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="zqt-d8-yas"/>
</constraints>
@ -1690,14 +1690,14 @@ DQ
<customObject id="Udi-3T-gMi" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<viewController title=" Preferences " id="ZT5-cA-xLj" customClass="PreferencesViewController" customModule="Clocker" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="DlQ-34-TgP" customClass="ParentView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="633" height="506"/>
<rect key="frame" x="0.0" y="0.0" width="633" height="514"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView wantsLayer="YES" distribution="fill" orientation="vertical" alignment="centerX" spacing="6" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1sT-pO-jK4">
<rect key="frame" x="7" y="0.0" width="618" height="506"/>
<stackView wantsLayer="YES" distribution="fill" orientation="vertical" alignment="centerX" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1sT-pO-jK4">
<rect key="frame" x="7" y="0.0" width="618" height="514"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="J2K-hR-0jv">
<rect key="frame" x="0.0" y="476" width="613" height="30"/>
<rect key="frame" x="0.0" y="484" width="613" height="30"/>
<subviews>
<button toolTip="Sorts by time difference from your current timezone" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="P6d-qq-ycq">
<rect key="frame" x="277" y="3" width="13" height="25"/>
@ -1756,7 +1756,7 @@ DQ
</constraints>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="eI7-Vb-R7J">
<rect key="frame" x="0.0" y="58" width="618" height="412"/>
<rect key="frame" x="0.0" y="62" width="618" height="412"/>
<subviews>
<scrollView wantsLayer="YES" focusRingType="none" borderType="none" horizontalLineScroll="62" horizontalPageScroll="10" verticalLineScroll="62" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zpF-gE-u0C">
<rect key="frame" x="0.0" y="0.0" width="618" height="412"/>
@ -1765,7 +1765,7 @@ DQ
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" autosaveColumns="NO" rowHeight="60" headerView="1hb-YT-szP" id="p9D-mN-dTa">
<rect key="frame" x="0.0" y="0.0" width="618" height="387"/>
<rect key="frame" x="0.0" y="0.0" width="624" height="387"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -1782,7 +1782,7 @@ DQ
</buttonCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="formattedAddress" editable="NO" width="260" minWidth="260" maxWidth="260" id="Kib-up-9ur">
<tableColumn identifier="formattedAddress" editable="NO" width="280" minWidth="280" maxWidth="280" id="Kib-up-9ur">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Name">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -1794,7 +1794,7 @@ DQ
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="label" width="240" minWidth="240" maxWidth="240" id="Fbd-Q4-EZ0">
<tableColumn identifier="label" width="280" minWidth="280" maxWidth="280" id="Fbd-Q4-EZ0">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Label">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
@ -1823,7 +1823,7 @@ DQ
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" focusRingType="none" id="1hb-YT-szP">
<rect key="frame" x="0.0" y="0.0" width="618" height="25"/>
<rect key="frame" x="0.0" y="0.0" width="624" height="25"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>

Loading…
Cancel
Save