Full Code of n0shake/Clocker for AI

master 18778bad0ec9 cached
547 files
2.4 MB
651.8k tokens
77 symbols
1 requests
Download .txt
Showing preview only (2,621K chars total). Download the full file or copy to clipboard to get everything.
Repository: n0shake/Clocker
Branch: master
Commit: 18778bad0ec9
Files: 547
Total size: 2.4 MB

Directory structure:
gitextract_ww47k156/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .swiftformat
├── .swiftlint.yml
├── .travis.yml
├── Archive/
│   └── New Icons/
│       └── Older Icons/
│           ├── New Icons/
│           │   └── NewIcon.xcf
│           └── Old Icons/
│               └── ClockerIcon.xcf
├── CLAUDE.md
├── Clocker/
│   ├── AppDelegate.swift
│   ├── Clocker/
│   │   ├── Clocker-Info.plist
│   │   ├── Clocker-Prefix.pch
│   │   ├── Clocker.entitlements
│   │   ├── LocationController.swift
│   │   ├── MainMenu.xib
│   │   ├── ShortcutRecorder-master/
│   │   │   ├── .gitignore
│   │   │   ├── LICENSE.md
│   │   │   ├── Library/
│   │   │   │   ├── Info.plist
│   │   │   │   ├── Prefix.pch
│   │   │   │   ├── SRCommon.h
│   │   │   │   ├── SRCommon.m
│   │   │   │   ├── SRKeyCodeTransformer.h
│   │   │   │   ├── SRKeyCodeTransformer.m
│   │   │   │   ├── SRKeyEquivalentModifierMaskTransformer.h
│   │   │   │   ├── SRKeyEquivalentModifierMaskTransformer.m
│   │   │   │   ├── SRKeyEquivalentTransformer.h
│   │   │   │   ├── SRKeyEquivalentTransformer.m
│   │   │   │   ├── SRModifierFlagsTransformer.h
│   │   │   │   ├── SRModifierFlagsTransformer.m
│   │   │   │   ├── SRRecorderControl.h
│   │   │   │   ├── SRRecorderControl.m
│   │   │   │   ├── SRValidator.h
│   │   │   │   ├── SRValidator.m
│   │   │   │   └── ShortcutRecorder.h
│   │   │   ├── PTHotKey/
│   │   │   │   ├── Info.plist
│   │   │   │   ├── PTHotKey+ShortcutRecorder.h
│   │   │   │   ├── PTHotKey+ShortcutRecorder.m
│   │   │   │   ├── PTHotKey.h
│   │   │   │   ├── PTHotKey.m
│   │   │   │   ├── PTHotKeyCenter.h
│   │   │   │   ├── PTHotKeyCenter.m
│   │   │   │   ├── PTKeyCodeTranslator.h
│   │   │   │   ├── PTKeyCodeTranslator.m
│   │   │   │   ├── PTKeyCombo.h
│   │   │   │   └── PTKeyCombo.m
│   │   │   ├── README.md
│   │   │   ├── Resources/
│   │   │   │   ├── LICENSE.txt
│   │   │   │   ├── ShorcutRecorder Yosemite.sketch
│   │   │   │   ├── ar.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ca.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── cs.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── de.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── el.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── en.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── es-MX.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── es.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── fr.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── it.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ja.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ko.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── nb.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── nl.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pl.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pt-BR.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pt.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ro.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ru.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── sk.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── sv.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── th.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── tr.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── zh-Hans.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   └── zh-Hant.lproj/
│   │   │   │       └── ShortcutRecorder.strings
│   │   │   ├── ShortcutRecorder.podspec
│   │   │   └── ShortcutRecorder.xcodeproj/
│   │   │       ├── project.pbxproj
│   │   │       └── xcshareddata/
│   │   │           └── xcschemes/
│   │   │               ├── PTHotKey.framework.xcscheme
│   │   │               └── ShortcutRecorder.framework.xcscheme
│   │   ├── ar.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ca.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── com.abhishek.ClockerHelper.plist
│   │   ├── de.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── en.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   ├── Localizable.strings
│   │   │   └── Panel.xib
│   │   ├── es.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── fr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── hi.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── hr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── it.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ja.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ko.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── main.m
│   │   ├── nl.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── pl.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── pt-BR.lproj/
│   │   │   └── Localizable.strings
│   │   ├── pt-PT.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── ru.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── tr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── uk.lproj/
│   │   │   └── Localizable.strings
│   │   ├── zh-Hans.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   └── zh-Hant.lproj/
│   │       └── Localizable.strings
│   ├── Clocker-Bridging-Header.h
│   ├── Clocker.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   ├── xcshareddata/
│   │   │   │   ├── Clocker.xcscmblueprint
│   │   │   │   ├── IDEWorkspaceChecks.plist
│   │   │   │   └── WorkspaceSettings.xcsettings
│   │   │   └── xcuserdata/
│   │   │       ├── abhishek_banthia.xcuserdatad/
│   │   │       │   └── WorkspaceSettings.xcsettings
│   │   │       ├── abhishekbanthia.xcuserdatad/
│   │   │       │   └── IDEFindNavigatorScopes.plist
│   │   │       └── ban.xcuserdatad/
│   │   │           └── IDEFindNavigatorScopes.plist
│   │   ├── xcshareddata/
│   │   │   ├── IDETemplateMacros.plist
│   │   │   └── xcschemes/
│   │   │       ├── Clocker.xcscheme
│   │   │       └── Tests.xcscheme
│   │   └── xcuserdata/
│   │       ├── abhi.xcuserdatad/
│   │       │   └── xcschemes/
│   │       │       └── xcschememanagement.plist
│   │       ├── abhishek_banthia.xcuserdatad/
│   │       │   └── xcschemes/
│   │       │       ├── Clocker.xcscheme
│   │       │       ├── ClockerHelper.xcscheme
│   │       │       └── xcschememanagement.plist
│   │       ├── abhishekbanthia.xcuserdatad/
│   │       │   ├── xcdebugger/
│   │       │   │   └── Breakpoints_v2.xcbkptlist
│   │       │   └── xcschemes/
│   │       │       ├── ClockerHelper.xcscheme
│   │       │       └── xcschememanagement.plist
│   │       └── ban.xcuserdatad/
│   │           ├── xcdebugger/
│   │           │   └── Breakpoints_v2.xcbkptlist
│   │           └── xcschemes/
│   │               └── xcschememanagement.plist
│   ├── ClockerHelper/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   └── Main.storyboard
│   │   ├── ClockerHelper.entitlements
│   │   ├── Info.plist
│   │   ├── de.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Main.strings
│   │   ├── main.m
│   │   ├── ru.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Main.strings
│   │   └── zh-Hans.lproj/
│   │       ├── InfoPlist.strings
│   │       └── Main.strings
│   ├── ClockerUITests/
│   │   ├── AboutUsTests.swift
│   │   ├── ClockerUITests-Bridging-Header.h
│   │   ├── ClockerUITests.m
│   │   ├── CopyToClipboardTests.swift
│   │   ├── FloatingWindowTests.swift
│   │   ├── Info.plist
│   │   ├── NetworkDisconnectionTests.swift
│   │   ├── OnboardingSearchTests.swift
│   │   ├── OnboardingTests.swift
│   │   ├── PanelTests.swift
│   │   ├── PermissionsTests.swift
│   │   ├── PreferencesTest.swift
│   │   ├── ReviewTests.swift
│   │   ├── ShortcutTests.swift
│   │   ├── de.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── ru.lproj/
│   │   │   └── InfoPlist.strings
│   │   └── zh-Hans.lproj/
│   │       └── InfoPlist.strings
│   ├── ClockerUnitTests/
│   │   ├── AppDelegateTests.swift
│   │   ├── ClockerUnitTests.swift
│   │   ├── DateFormatterManagerTests.swift
│   │   ├── EventInfoTests.swift
│   │   ├── Info.plist
│   │   ├── ReviewControllerTests.swift
│   │   ├── SearchDataSourceTests.swift
│   │   ├── StandardMenubarHandlerTests.swift
│   │   └── ThemerTests.swift
│   ├── CoreLoggerKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   ├── Sources/
│   │   │   └── CoreLoggerKit/
│   │   │       └── Logger.swift
│   │   └── Tests/
│   │       ├── CoreLoggerKitTests/
│   │       │   ├── CoreLoggerKitTests.swift
│   │       │   └── XCTestManifests.swift
│   │       └── LinuxMain.swift
│   ├── CoreModelKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   ├── Sources/
│   │   │   └── CoreModelKit/
│   │   │       ├── SearchResults.swift
│   │   │       └── TimezoneData.swift
│   │   └── Tests/
│   │       ├── CoreModelKitTests/
│   │       │   ├── TimezoneDataEqualityTests.swift
│   │       │   └── XCTestManifests.swift
│   │       └── LinuxMain.swift
│   ├── Dependencies/
│   │   ├── Date Additions/
│   │   │   ├── Constants.swift
│   │   │   ├── Date+Bundle.swift
│   │   │   ├── Date+Comparators.swift
│   │   │   ├── Date+Components.swift
│   │   │   ├── Date+Format.swift
│   │   │   ├── Date+Inits.swift
│   │   │   ├── Date+Manipulations.swift
│   │   │   ├── Date+TimeAgo.swift
│   │   │   ├── DateTools.bundle/
│   │   │   │   ├── am.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ar.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── bg.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ca.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── cs.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── cy.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── da.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── de.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── en.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── es.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── eu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── fi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── fr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── gre.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── gu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── he.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── id.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── is.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── it.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ja.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ko.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── lv.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ms.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── nb.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── nl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pt-PT.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pt.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ro.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ru.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── sk.lproj/
│   │   │   │   │   └── NSDateTimeAgo.strings
│   │   │   │   ├── sl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── sv.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── th.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── tr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── uk.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── vi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── zh-Hans.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   └── zh-Hant.lproj/
│   │   │   │       └── DateTools.strings
│   │   │   ├── Enums.swift
│   │   │   ├── Integer+DateTools.swift
│   │   │   └── TimeChunk.swift
│   │   ├── Solar.swift
│   │   └── iVersion/
│   │       ├── iVersion.bundle/
│   │       │   ├── da.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── de.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── el.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── en-GB.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── en.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── es.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── fr.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── it.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── ja.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── pt-PT.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── pt.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── ru.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── tr.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── zh-Hans.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   └── zh-Hant.lproj/
│   │       │       └── Localizable.strings
│   │       ├── iVersion.h
│   │       └── iVersion.m
│   ├── Events and Reminders/
│   │   ├── CalendarHandler.swift
│   │   ├── EventCenter.swift
│   │   └── RemindersHandler.swift
│   ├── Firebase.h
│   ├── Frameworks/
│   │   └── Firebase/
│   │       ├── FirebaseCore.framework/
│   │       │   ├── FirebaseCore
│   │       │   ├── Headers/
│   │       │   │   ├── FIRApp.h
│   │       │   │   ├── FIRConfiguration.h
│   │       │   │   ├── FIRLoggerLevel.h
│   │       │   │   ├── FIROptions.h
│   │       │   │   ├── FIRVersion.h
│   │       │   │   └── FirebaseCore.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseCoreDiagnostics.framework/
│   │       │   ├── FirebaseCoreDiagnostics
│   │       │   ├── Headers/
│   │       │   │   ├── FIRCoreDiagnostics.h
│   │       │   │   └── FirebaseCoreDiagnostics-umbrella.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseCrashlytics.framework/
│   │       │   ├── FirebaseCrashlytics
│   │       │   ├── Headers/
│   │       │   │   ├── FIRCrashlytics.h
│   │       │   │   ├── FIRCrashlyticsReport.h
│   │       │   │   ├── FIRExceptionModel.h
│   │       │   │   ├── FIRStackFrame.h
│   │       │   │   └── FirebaseCrashlytics.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseDatabase.framework/
│   │       │   ├── FirebaseDatabase
│   │       │   ├── Headers/
│   │       │   │   ├── FIRDataEventType.h
│   │       │   │   ├── FIRDataSnapshot.h
│   │       │   │   ├── FIRDatabase.h
│   │       │   │   ├── FIRDatabaseQuery.h
│   │       │   │   ├── FIRDatabaseReference.h
│   │       │   │   ├── FIRMutableData.h
│   │       │   │   ├── FIRServerValue.h
│   │       │   │   ├── FIRTransactionResult.h
│   │       │   │   └── FirebaseDatabase.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseInstallations.framework/
│   │       │   ├── FirebaseInstallations
│   │       │   ├── Headers/
│   │       │   │   ├── FIRInstallations.h
│   │       │   │   ├── FIRInstallationsAuthTokenResult.h
│   │       │   │   ├── FIRInstallationsErrors.h
│   │       │   │   └── FirebaseInstallations.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── GoogleDataTransport.framework/
│   │       │   ├── GoogleDataTransport
│   │       │   ├── Headers/
│   │       │   │   ├── GDTCORClock.h
│   │       │   │   ├── GDTCORConsoleLogger.h
│   │       │   │   ├── GDTCOREndpoints.h
│   │       │   │   ├── GDTCOREvent.h
│   │       │   │   ├── GDTCOREventDataObject.h
│   │       │   │   ├── GDTCOREventTransformer.h
│   │       │   │   ├── GDTCORTargets.h
│   │       │   │   ├── GDTCORTransport.h
│   │       │   │   └── GoogleDataTransport.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── GoogleUtilities.framework/
│   │       │   ├── GoogleUtilities
│   │       │   ├── Headers/
│   │       │   │   ├── GULAppDelegateSwizzler.h
│   │       │   │   ├── GULAppEnvironmentUtil.h
│   │       │   │   ├── GULApplication.h
│   │       │   │   ├── GULHeartbeatDateStorable.h
│   │       │   │   ├── GULHeartbeatDateStorage.h
│   │       │   │   ├── GULHeartbeatDateStorageUserDefaults.h
│   │       │   │   ├── GULKeychainStorage.h
│   │       │   │   ├── GULKeychainUtils.h
│   │       │   │   ├── GULLogger.h
│   │       │   │   ├── GULLoggerLevel.h
│   │       │   │   ├── GULMutableDictionary.h
│   │       │   │   ├── GULNSData+zlib.h
│   │       │   │   ├── GULNetwork.h
│   │       │   │   ├── GULNetworkConstants.h
│   │       │   │   ├── GULNetworkLoggerProtocol.h
│   │       │   │   ├── GULNetworkMessageCode.h
│   │       │   │   ├── GULNetworkURLSession.h
│   │       │   │   ├── GULReachabilityChecker.h
│   │       │   │   ├── GULSceneDelegateSwizzler.h
│   │       │   │   ├── GULSecureCoding.h
│   │       │   │   ├── GULURLSessionDataResponse.h
│   │       │   │   ├── GULUserDefaults.h
│   │       │   │   ├── GoogleUtilities-umbrella.h
│   │       │   │   └── NSURLSession+GULPromises.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── PromisesObjC.framework/
│   │       │   ├── Headers/
│   │       │   │   ├── FBLPromise+All.h
│   │       │   │   ├── FBLPromise+Always.h
│   │       │   │   ├── FBLPromise+Any.h
│   │       │   │   ├── FBLPromise+Async.h
│   │       │   │   ├── FBLPromise+Await.h
│   │       │   │   ├── FBLPromise+Catch.h
│   │       │   │   ├── FBLPromise+Delay.h
│   │       │   │   ├── FBLPromise+Do.h
│   │       │   │   ├── FBLPromise+Race.h
│   │       │   │   ├── FBLPromise+Recover.h
│   │       │   │   ├── FBLPromise+Reduce.h
│   │       │   │   ├── FBLPromise+Retry.h
│   │       │   │   ├── FBLPromise+Testing.h
│   │       │   │   ├── FBLPromise+Then.h
│   │       │   │   ├── FBLPromise+Timeout.h
│   │       │   │   ├── FBLPromise+Validate.h
│   │       │   │   ├── FBLPromise+Wrap.h
│   │       │   │   ├── FBLPromise.h
│   │       │   │   ├── FBLPromiseError.h
│   │       │   │   ├── FBLPromises.h
│   │       │   │   └── PromisesObjC-umbrella.h
│   │       │   ├── Info.plist
│   │       │   ├── Modules/
│   │       │   │   └── module.modulemap
│   │       │   └── PromisesObjC
│   │       ├── leveldb-library.framework/
│   │       │   ├── Headers/
│   │       │   │   ├── c.h
│   │       │   │   ├── cache.h
│   │       │   │   ├── comparator.h
│   │       │   │   ├── db.h
│   │       │   │   ├── dumpfile.h
│   │       │   │   ├── env.h
│   │       │   │   ├── export.h
│   │       │   │   ├── filter_policy.h
│   │       │   │   ├── iterator.h
│   │       │   │   ├── leveldb-library-umbrella.h
│   │       │   │   ├── options.h
│   │       │   │   ├── slice.h
│   │       │   │   ├── status.h
│   │       │   │   ├── table.h
│   │       │   │   ├── table_builder.h
│   │       │   │   └── write_batch.h
│   │       │   ├── Info.plist
│   │       │   ├── Modules/
│   │       │   │   └── module.modulemap
│   │       │   └── leveldb-library
│   │       └── nanopb.framework/
│   │           ├── Headers/
│   │           │   ├── nanopb-umbrella.h
│   │           │   ├── pb.h
│   │           │   ├── pb_common.h
│   │           │   ├── pb_decode.h
│   │           │   └── pb_encode.h
│   │           ├── Info.plist
│   │           ├── Modules/
│   │           │   └── module.modulemap
│   │           └── nanopb
│   ├── GoogleService-Info.plist
│   ├── Keys.plist.example
│   ├── Media.xcassets/
│   │   ├── Accent Color.colorset/
│   │   │   └── Contents.json
│   │   ├── Add Icon/
│   │   │   ├── Add Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add Highlighted.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add Icon.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Calendar Icon Remove/
│   │   │   ├── Contents.json
│   │   │   ├── Remove Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Remove.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── WhiteRemove.imageset/
│   │   │       └── Contents.json
│   │   ├── Clocker Icon/
│   │   │   ├── ClockerIcon-512.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── Extra Options/
│   │   │   ├── Contents.json
│   │   │   ├── Extra Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Extra.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraHighlighted Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraHighlighted.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraWhite.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── ExtraWhiteHighlighted.imageset/
│   │   │       └── Contents.json
│   │   ├── Location/
│   │   │   ├── Contents.json
│   │   │   ├── CurrentLocation.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── CurrentLocationDynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── CurrentLocationWhite.imageset/
│   │   │       └── Contents.json
│   │   ├── Menubar Icons/
│   │   │   ├── Contents.json
│   │   │   └── LightModeIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Onboarding/
│   │   │   ├── Contents.json
│   │   │   ├── Dark Menubar.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Dynamic Menubar.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Light Menubar.imageset/
│   │   │       └── Contents.json
│   │   ├── Pin/
│   │   │   ├── Contents.json
│   │   │   ├── Float-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Float.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Pin.imageset/
│   │   │       └── Contents.json
│   │   ├── Power Icon/
│   │   │   ├── Contents.json
│   │   │   ├── Power.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── PowerIcon-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── PowerIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Preferences Toolbar.imageset/
│   │   │   └── Contents.json
│   │   ├── Privacy/
│   │   │   ├── Contents.json
│   │   │   ├── Privacy Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Privacy Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Privacy.imageset/
│   │   │       └── Contents.json
│   │   ├── Settings/
│   │   │   ├── Contents.json
│   │   │   ├── Settings-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Settings.imageset/
│   │   │       └── Contents.json
│   │   ├── Sharing/
│   │   │   ├── Contents.json
│   │   │   ├── Sharing Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sharing.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── SharingDarkIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Sunrise/
│   │   │   ├── Contents.json
│   │   │   ├── Sunrise Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunrise.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunset Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunset.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── WhiteSunrise.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── WhiteSunset.imageset/
│   │   │       └── Contents.json
│   │   ├── Tabs/
│   │   │   ├── Appearance Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Appearance Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Appearance.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Icon.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   └── Trash.imageset/
│   │       └── Contents.json
│   ├── Menu Bar/
│   │   ├── MenubarHandler.swift
│   │   ├── StatusContainerView.swift
│   │   ├── StatusItemHandler.swift
│   │   └── StatusItemView.swift
│   ├── Onboarding/
│   │   ├── FinalOnboardingViewController.swift
│   │   ├── Onboarding.storyboard
│   │   ├── OnboardingController.swift
│   │   ├── OnboardingParentViewController.swift
│   │   ├── OnboardingPermissionsViewController.swift
│   │   ├── OnboardingSearchController.swift
│   │   ├── OnboardingWelcomeViewController.swift
│   │   ├── StartAtLoginViewController.swift
│   │   └── WelcomeView.xib
│   ├── Overall App/
│   │   ├── AppDefaults.swift
│   │   ├── AppKit + Additions.swift
│   │   ├── ConfigExport.swift
│   │   ├── DataStore.swift
│   │   ├── DateFormatterManager.swift
│   │   ├── Foundation + Additions.swift
│   │   ├── NetworkManager.swift
│   │   ├── Reach.swift
│   │   ├── String + Additions.swift
│   │   ├── Strings.swift
│   │   ├── Themer.swift
│   │   ├── Timer.swift
│   │   ├── UserDefaults + KVOExtensions.swift
│   │   └── VersionUpdateHandler.swift
│   ├── Panel/
│   │   ├── Data Layer/
│   │   │   └── TimezoneDataOperations.swift
│   │   ├── FloatingWindowController.swift
│   │   ├── Notes Popover/
│   │   │   ├── NotesPopover.swift
│   │   │   ├── NotesPopover.xib
│   │   │   └── TextViewWithPlaceholder.swift
│   │   ├── PanelController.swift
│   │   ├── ParentPanelController+ModernSlider.swift
│   │   ├── ParentPanelController.swift
│   │   ├── Rate Controller/
│   │   │   ├── ReviewController.swift
│   │   │   └── UpcomingEventView.swift
│   │   ├── UI/
│   │   │   ├── AddTableViewCell.swift
│   │   │   ├── BackgroundPanelView.swift
│   │   │   ├── CustomSliderCell.swift
│   │   │   ├── FloatingWindow.xib
│   │   │   ├── HourMarkerViewItem.xib
│   │   │   ├── NoTimezoneView.swift
│   │   │   ├── PanelTableView.swift
│   │   │   ├── Panelr.swift
│   │   │   ├── TimeMarkerViewItem.swift
│   │   │   ├── TimezoneCellView.swift
│   │   │   ├── TimezoneDataSource.swift
│   │   │   └── Toasty.swift
│   │   └── Upcoming Events/
│   │       ├── ParentPanelController+UpcomingEvents.swift
│   │       ├── UpcomingEventViewItem.swift
│   │       ├── UpcomingEventViewItem.xib
│   │       └── UpcomingEventsDataSource.swift
│   ├── Preferences/
│   │   ├── About/
│   │   │   ├── AboutViewController.swift
│   │   │   └── PointingHandCursorButton.swift
│   │   ├── App Feedback/
│   │   │   ├── AppFeedbackWindow.xib
│   │   │   └── AppFeedbackWindowController.swift
│   │   ├── Appearance/
│   │   │   └── AppearanceViewController.swift
│   │   ├── Calendar/
│   │   │   └── CalendarViewController.swift
│   │   ├── General/
│   │   │   ├── PreferencesDataSource.swift
│   │   │   ├── PreferencesViewController.swift
│   │   │   └── SearchDataSource.swift
│   │   ├── Menu Bar/
│   │   │   ├── MenubarTitleProvider.swift
│   │   │   ├── StatusContainerView.swift
│   │   │   ├── StatusItemHandler.swift
│   │   │   ├── StatusItemView.swift
│   │   │   └── UpcomingEventStatusItemView.swift
│   │   ├── OneWindowController.swift
│   │   ├── ParentViewController.swift
│   │   ├── Permissions/
│   │   │   └── PermissionsViewController.swift
│   │   ├── Preferences.storyboard
│   │   └── StartupManager.swift
│   ├── Releases/
│   │   ├── appcast.xml
│   │   └── changelog.md
│   ├── StartupKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   └── Sources/
│   │       └── StartupKit/
│   │           └── StartupManager.swift
│   ├── release.py
│   ├── run
│   └── upload-symbols
├── Readme.md
└── swiftlint-install.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: n0shake


================================================
FILE: .gitignore
================================================

*.xcuserstate
.DS_Store
.DS_Store
Clocker/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishek_banthia.xcuserdatad/UserInterfaceState.xcuserstate
Clocker/Clocker.xcodeproj/xcuserdata/abhishek_banthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
*.xcuserstate
.DS_Store
**/Keys.plist


================================================
FILE: .swiftformat
================================================
--disable

================================================
FILE: .swiftlint.yml
================================================
disabled_rules: # rule identifiers to exclude from running
  - type_body_length
  - file_length
  - type_name
  - variable_name
  - nesting
opt_in_rules: # some rules are only opt-in
  - empty_count
# included: # paths to include during linting. `--path` is ignored if present.
#   - Clocker
excluded: # paths to ignore during linting. Takes precedence over `included`.
  - Clocker/Dependencies
  - Clocker/ClockerUnitTests
  - Clocker/ClockerUITests
  # - Pods
  # - Source/ExcludedFolder
  # - Source/ExcludedFile.swift
  # - Source/*/ExcludedFile.swift # Exclude files with a wildcard
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
  - explicit_self

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
force_cast: warning # implicitly
force_try:
  severity: warning # explicitly
# rules that have both warning and error levels, can set just the warning level
# implicitly
line_length: 200
# they can set both implicitly with an array
type_body_length:
  - 300 # warning
  - 400 # error
# or they can set both explicitly
file_length:
  warning: 500
  error: 1200
# naming rules can set warnings/errors for min_length and max_length
# additionally they can set excluded names
type_name:
  min_length: 3 # only warning
  max_length: # warning and error
    warning: 40
    error: 50
  excluded: iPhone # excluded via string
identifier_name:
  min_length: # only min_length
    error: 3 # only error
  # excluded: # excluded via string array
  #   - id
  #   - URL
  #   - GlobalAPIKey
reporter: "xcode" 

================================================
FILE: .travis.yml
================================================
os: osx
language: swift
xcode_project: Clocker.xcodeproj # path to your xcodeproj folder
osx_image: xcode12.2
before_install:
- export TZ=America/Chicago
before_script:
 - xcodebuild -version
install:
 - ./swiftlint-install.sh
script:
 - set -o pipefail && env "NSUnbufferedIO=YES"
 - pwd
 - swiftlint
 - xcodebuild -project Clocker/Clocker.xcodeproj -scheme Clocker build analyze CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY= | xcpretty
 - xcodebuild -project Clocker/Clocker.xcodeproj -scheme Clocker test CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY=  | xcpretty


================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Clocker is a macOS menu bar utility (Swift 5, AppKit) that helps users track time across different time zones. It's a native macOS app targeting Sierra 10.12+, distributed via the Mac App Store and Homebrew.

## Build & Test Commands

```bash
# Build
xcodebuild -project Clocker/Clocker.xcodeproj -scheme Clocker build

# Lint
swiftlint lint --path Clocker/Clocker

# Lint with analyzer rules (requires build)
swiftlint analyze --compiler-log-path build/CompileSwift.log
```

The project uses Xcode directly — open `Clocker/Clocker.xcodeproj` for day-to-day development.

## Verification Policy

**Only build to verify changes — never run unit tests.** Use `xcodebuild ... build` to confirm the project compiles. Tests must be run manually from within Xcode.

Unit tests via `xcodebuild ... test` launch the full app host process, which can produce misleading fatal errors unrelated to the change under review. UI tests cannot be run via xcodebuild at all due to a code signing Team ID mismatch between the app and the UI test runner bundle.

## Architecture

### Module Structure

The app is split into the main `Clocker` target plus three Swift packages:
- **CoreModelKit** — data models (`TimezoneData`, `SearchResults`, etc.)
- **CoreLoggerKit** — centralized logging
- **StartupKit** — app initialization/startup orchestration

### Feature Modules (inside `Clocker/Clocker/`)

| Directory | Purpose |
|-----------|---------|
| `Overall App/` | App-wide services: `DataStore`, `AppDefaults`, `Themer`, `DateFormatterManager`, `NetworkManager` |
| `Menu Bar/` | `StatusItemHandler`, `MenubarHandler` — manages the menu bar status item |
| `Panel/` | Main UI panel: `ParentPanelController` (primary controller), `PanelController`, `FloatingWindowController`, `TimezoneDataSource`, `TimezoneDataOperations` |
| `Preferences/` | Settings UI split into General, Appearance, Menu Bar, Calendar, and About sub-controllers |
| `Onboarding/` | First-run flow: search, permissions, start-at-login, and final screens |
| `Events and Reminders/` | `EventCenter`, `CalendarHandler`, `RemindersHandler` for OS calendar/reminder integration |

### Key Data Flow

```
AppDelegate
  └── StatusItemHandler (menu bar)
  └── PanelController / FloatingWindowController
        └── ParentPanelController
              ├── TimezoneDataSource  ←→  DataStore (UserDefaults)
              └── UpcomingEventsDataSource  ←→  EventCenter
```

`DataStore` is the single source of truth for persisted timezone list and settings; it wraps `UserDefaults` and is accessed throughout the app as a shared instance.

### Panel vs. Floating Window

The app has two display modes controlled by a user preference:
- **Panel** (`PanelController`) — anchored to the menu bar item
- **Floating Window** (`FloatingWindowController`) — free-floating, always-on-top window

Both share `ParentPanelController` for the core UI logic (time display, slider scrubbing, upcoming events).

### Theming

`Themer.swift` manages light/dark/system appearance. UI components observe `Themer` notifications to update colors. Always use `Themer` for colors rather than hardcoded values.

## SwiftLint Configuration

Line length limit: 200. `explicit_self` is enforced via the analyzer rules. Tests and `Dependencies/` are excluded from linting.

## Release Process

`release.py` automates version bumping (`agvtool`), clean build+analyze, test run, and GitHub release creation. Firebase Crashlytics is integrated for crash reporting in Release builds only.


================================================
FILE: Clocker/AppDelegate.swift
================================================
// Copyright © 2015 Abhishek Banthia

import Cocoa
import CoreLoggerKit
import CoreModelKit
import FirebaseCore
import FirebaseCrashlytics

open class AppDelegate: NSObject, NSApplicationDelegate {
    private lazy var floatingWindow = FloatingWindowController.shared()
    internal lazy var panelController = PanelController(windowNibName: .panel)
    private var statusBarHandler: StatusItemHandler!
    
    // TODO: Replace iVersion with this!
//    private let versionUpdateHandler: VersionUpdateHandler = VersionUpdateHandler(with: DataStore.shared())

    override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
        if let path = keyPath, path == PreferencesConstants.hotKeyPathIdentifier {
            let hotKeyCenter = PTHotKeyCenter.shared()

            // Unregister old hot key
            let oldHotKey = hotKeyCenter?.hotKey(withIdentifier: path)
            hotKeyCenter?.unregisterHotKey(oldHotKey)

            // We don't register unless there's a valid key combination
            guard let newObject = object as? NSObject, let newShortcut = newObject.value(forKeyPath: path) as? [AnyHashable: Any] else {
                return
            }

            // Register new key
            let newHotKey = PTHotKey(identifier: keyPath,
                                     keyCombo: newShortcut,
                                     target: self,
                                     action: #selector(ping(_:)))

            hotKeyCenter?.register(newHotKey)
        }
    }

    public func applicationDidFinishLaunching(_: Notification) {
        AppDefaults.initialize(with: DataStore.shared(), defaults: UserDefaults.standard)

        // Check if we can show the onboarding flow!
        showOnboardingFlowIfEligible()

        // Ratings Controller initialization
        ReviewController.applicationDidLaunch(UserDefaults.standard)

        #if RELEASE
            FirebaseApp.configure()
            checkIfRunFromApplicationsFolder()
        #endif
    }
  
    public func applicationWillFinishLaunching(_: Notification) {
        iVersion.sharedInstance().useAllAvailableLanguages = true
        iVersion.sharedInstance().verboseLogging = false
    }

    public func applicationDockMenu(_: NSApplication) -> NSMenu? {
        let menu = NSMenu(title: "Quick Access")

        let toggleMenuItem = NSMenuItem(title: "Toggle Panel", action: #selector(AppDelegate.togglePanel(_:)), keyEquivalent: "")
        let openPreferences = NSMenuItem(title: "Settings", action: #selector(AppDelegate.openPreferencesWindow), keyEquivalent: ",")
        let hideFromDockMenuItem = NSMenuItem(title: "Hide from Dock", action: #selector(AppDelegate.hideFromDock), keyEquivalent: "")

        [toggleMenuItem, openPreferences, hideFromDockMenuItem].forEach {
            $0.isEnabled = true
            menu.addItem($0)
        }

        return menu
    }

    @objc private func openPreferencesWindow() {
        let displayMode = DataStore.shared().shouldDisplay(.showAppInForeground)

        if displayMode {
            let floatingWindow = FloatingWindowController.shared()
            floatingWindow.openPreferences(NSButton())
        } else {
            panelController.openPreferences(NSButton())
        }
    }

    @objc func hideFromDock() {
        UserDefaults.standard.set(0, forKey: UserDefaultKeys.appDisplayOptions)
        NSApp.setActivationPolicy(.accessory)
    }

    private var controller: OnboardingController?

    private func showOnboardingFlowIfEligible() {
        let isTestInProgress = ProcessInfo.processInfo.arguments.contains(UserDefaultKeys.onboardingTestsLaunchArgument)
        let shouldLaunchOnboarding =
        (DataStore.shared().retrieve(key: UserDefaultKeys.showOnboardingFlow) == nil
                && DataStore.shared().timezones().isEmpty)
            || isTestInProgress

        if shouldLaunchOnboarding {
            let onboardingStoryboard = NSStoryboard(name: NSStoryboard.Name("Onboarding"), bundle: nil)
            controller = onboardingStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("onboardingFlow")) as? OnboardingController
            controller?.launch()
        } else {
            continueUsually()
        }
    }

    func continueUsually() {
        // Cleanup onboarding controller after its done!
        if controller != nil {
            controller = nil
        }

        // Check if another instance of the app is already running. If so, then stop this one.
        checkIfAppIsAlreadyOpen()

        // Install the menubar item!
        statusBarHandler = StatusItemHandler(with: DataStore.shared())

        if ProcessInfo.processInfo.arguments.contains(UserDefaultKeys.testingLaunchArgument) {
            FirebaseApp.configure()
            ReviewController.setPreviewMode(true)
        }

        UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])

        assignShortcut()

        let defaults = UserDefaults.standard

        setActivationPolicy()

        // Set the display mode default as panel!
        if let displayMode = defaults.object(forKey: UserDefaultKeys.showAppInForeground) as? NSNumber, displayMode.intValue == 1 {
            showFloatingWindow()
        } else if let displayMode = defaults.object(forKey: UserDefaultKeys.showAppInForeground) as? Int, displayMode == 1 {
            showFloatingWindow()
        }
    }

    // Should we have a dock icon or just stay in the menubar?
    private func setActivationPolicy() {
        let defaults = UserDefaults.standard

        let currentActivationPolicy = NSRunningApplication.current.activationPolicy
        let activationPolicy: NSApplication.ActivationPolicy = defaults.integer(forKey: UserDefaultKeys.appDisplayOptions) == 0 ? .accessory : .regular

        if currentActivationPolicy != activationPolicy {
            NSApp.setActivationPolicy(activationPolicy)
        }
    }

    private func checkIfAppIsAlreadyOpen() {
        guard let bundleID = Bundle.main.bundleIdentifier else {
            return
        }

        let apps = NSRunningApplication.runningApplications(withBundleIdentifier: bundleID)

        if apps.count > 1 {
            let currentApplication = NSRunningApplication.current
            for app in apps where app != currentApplication {
                app.terminate()
            }
        }
    }

    private func showAlert(message: String, informativeText: String, buttonTitle: String) {
        NSApplication.shared.activate(ignoringOtherApps: true)
        let alert = NSAlert()
        alert.messageText = message
        alert.informativeText = informativeText
        alert.addButton(withTitle: buttonTitle)
        alert.runModal()
    }

    @IBAction func ping(_ sender: NSButton) {
        if let statusItemButton = statusBarHandler.statusItem.button {
            statusItemButton.state = statusItemButton.state == .on ? .off : .on
            togglePanel(statusItemButton)
        }
    }

    private func retrieveLatestLocation() {
        let locationController = LocationController(withStore: DataStore.shared())
        locationController.determineAndRequestLocationAuthorization()
    }

    private func showFloatingWindow() {
        // Display the Floating Window!
        floatingWindow.showWindow(nil)
        floatingWindow.updateTableContent()
        floatingWindow.startWindowTimer()

        NSApp.activate(ignoringOtherApps: true)
    }

    private func assignShortcut() {
        NSUserDefaultsController.shared.addObserver(self,
                                                    forKeyPath: PreferencesConstants.hotKeyPathIdentifier,
                                                    options: [.initial, .new],
                                                    context: nil)
    }

    private func checkIfRunFromApplicationsFolder() {
        if let shortCircuit = UserDefaults.standard.object(forKey: "AllowOutsideApplicationsFolder") as? Bool, shortCircuit == true {
            return
        }

        let bundlePath = Bundle.main.bundlePath
        let applicationDirectory = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationDirectory,
                                                                       FileManager.SearchPathDomainMask.localDomainMask,
                                                                       true)
        for appDir in applicationDirectory {
            if bundlePath.hasPrefix(appDir) {
                return
            }
        }

        let informativeText = """
        Clocker must be run from the Applications folder in order to work properly.
        Please quit Clocker, move it to the Applications folder, and relaunch.
        Current folder: \(applicationDirectory)"
        """

        // Clocker is installed out of Applications directory
        // This breaks start at login! Time to show an alert and terminate
        showAlert(message: "Move Clocker to the Applications folder",
                  informativeText: informativeText,
                  buttonTitle: "Quit")

        // Terminate
        NSApp.terminate(nil)
    }

    @IBAction open func togglePanel(_ sender: NSButton) {
        Logger.info("Toggle Panel called with sender state \(sender.state.rawValue)")
        let displayMode = UserDefaults.standard.integer(forKey: UserDefaultKeys.showAppInForeground)

        if displayMode == 1 {
            // No need to call NSApp.activate here since `showFloatingWindow` takes care of this
            showFloatingWindow()
        } else {
            panelController.showWindow(nil)
            panelController.setActivePanel(newValue: sender.state == .on)
            NSApp.activate(ignoringOtherApps: true)
        }
    }

    open func setupFloatingWindow(_ hide: Bool) {
        hide ? floatingWindow.window?.close() : showFloatingWindow()
    }

    func statusItemForPanel() -> StatusItemHandler {
        return statusBarHandler
    }

    open func setupMenubarTimer() {
        statusBarHandler.setupStatusItem()
    }

    open func invalidateMenubarTimer(_ showIcon: Bool) {
        statusBarHandler.invalidateTimer(showIcon: showIcon, isSyncing: true)
    }
}


================================================
FILE: Clocker/Clocker/Clocker-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>Clocker - World Clock</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(MARKETING_VERSION)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
	<key>ITSAppUsesNonExemptEncryption</key>
	<false/>
	<key>LSApplicationCategoryType</key>
	<string>public.app-category.utilities</string>
	<key>LSMinimumSystemVersion</key>
	<string>${MACOSX_DEPLOYMENT_TARGET}</string>
	<key>LSUIElement</key>
	<true/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>NSCalendarsUsageDescription</key>
	<string>Clocker can be more useful when it can display upcoming events from your calendars. You can change this setting in System Preferences › Security &amp; Privacy › Privacy</string>
	<key>NSHumanReadableCopyright</key>
	<string>Copyright © 2024, Abhishek Banthia</string>
	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
	<string>Clocker can be more useful when it can use your location to determine your current timezone.</string>
	<key>NSLocationUsageDescription</key>
	<string>Clocker can be more useful when it can use your location to determine your current timezone.</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
	<key>NSRemindersUsageDescription</key>
	<string>Clocker can be more useful when it can set reminders for your selected timezone(s). You can change this setting in System Preferences › Security &amp; Privacy › Privacy.</string>
	<key>NSSupportsAutomaticGraphicsSwitching</key>
	<true/>
	<key>RequestsOpenAccess</key>
	<string>YES</string>
</dict>
</plist>


================================================
FILE: Clocker/Clocker/Clocker-Prefix.pch
================================================
//
// Prefix header for all source files of the 'Clocker' target in the 'Clocker' project
//

#ifdef __OBJC__

#import <Cocoa/Cocoa.h>

#endif


================================================
FILE: Clocker/Clocker/Clocker.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.cs.disable-library-validation</key>
	<true/>
	<key>com.apple.security.network.client</key>
	<true/>
	<key>com.apple.security.personal-information.calendars</key>
	<true/>
	<key>com.apple.security.temporary-exception.apple-events</key>
	<array>
		<string>com.apple.reminders</string>
	</array>
</dict>
</plist>


================================================
FILE: Clocker/Clocker/LocationController.swift
================================================
// Copyright © 2015 Abhishek Banthia

import Cocoa
import CoreLocation
import CoreLoggerKit
import CoreModelKit

protocol LocationControllerDelegate: NSObject {
    func didChangeAuthorizationStatus()
}

class LocationController: NSObject {
    private let store: DataStore
    
    init(withStore dataStore: DataStore) {
        store = dataStore
        super.init()
    }

    private var locationManager: CLLocationManager = {
        let locationManager = CLLocationManager()
        locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
        return locationManager
    }()

    func authorizationStatus() -> CLAuthorizationStatus {
        return locationManager.authorizationStatus
    }

    func locationAccessNotDetermined() -> Bool {
        return locationManager.authorizationStatus == .notDetermined
    }

    func locationAccessGranted() -> Bool {
        print("Location Status is ", locationManager.authorizationStatus.rawValue.description)
        return locationManager.authorizationStatus == .authorizedAlways || locationManager.authorizationStatus == .authorized
    }

    func locationAccessDenied() -> Bool {
        return locationManager.authorizationStatus == .restricted || locationManager.authorizationStatus == .denied
    }

    func setDelegate() {
        locationManager.delegate = self
    }

    func determineAndRequestLocationAuthorization() {
        setDelegate()

        if CLLocationManager.locationServicesEnabled() {
            locationManager.startUpdatingLocation()
        }

        switch authorizationStatus() {
        case .authorizedAlways:
            locationManager.startUpdatingLocation()
        case .notDetermined:
            locationManager.startUpdatingLocation()
        case .denied, .restricted:
            locationManager.startUpdatingLocation()
        default:
            fatalError("Unexpected Authorization Status")
        }
    }

    private func updateHomeObject(with customLabel: String, coordinates: CLLocationCoordinate2D?) {
        let timezones = store.timezones()

        var timezoneObjects: [TimezoneData] = []

        for timezone in timezones {
            if let model = TimezoneData.customObject(from: timezone) {
                timezoneObjects.append(model)
            }
        }

        for timezoneObject in timezoneObjects where timezoneObject.isSystemTimezone == true {
            timezoneObject.setLabel(customLabel)
            if let latlong = coordinates {
                timezoneObject.longitude = latlong.longitude
                timezoneObject.latitude = latlong.latitude
            }
        }

        var datas: [Data] = []

        for updatedObject in timezoneObjects {
            guard let dataObject = NSKeyedArchiver.clocker_archive(with: updatedObject) else {
                continue
            }
            datas.append(dataObject)
        }

        store.setTimezones(datas)
    }
}

extension LocationController: CLLocationManagerDelegate {
    func locationManager(_: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard !locations.isEmpty, let coordinates = locations.first?.coordinate else { return }

        let reverseGeoCoder = CLGeocoder()

        reverseGeoCoder.reverseGeocodeLocation(locations[0]) { placemarks, _ in

            guard let customLabel = placemarks?.first?.locality else { return }

            self.updateHomeObject(with: customLabel, coordinates: coordinates)

            self.locationManager.stopUpdatingLocation()
        }
    }

    func locationManager(_: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .denied || status == .restricted {
            updateHomeObject(with: TimeZone.autoupdatingCurrent.identifier, coordinates: nil)
            locationManager.stopUpdatingLocation()
        } else if status == .notDetermined || status == .authorized || status == .authorizedAlways {
            locationManager.startUpdatingLocation()
        }
    }

    func locationManager(_: CLLocationManager, didFailWithError error: Error) {
        Logger.info(error.localizedDescription)
    }
}


================================================
FILE: Clocker/Clocker/MainMenu.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
            <connections>
                <outlet property="delegate" destination="494" id="495"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <menu title="AMainMenu" systemMenu="main" id="29">
            <items>
                <menuItem title="Clocker" id="56">
                    <menu key="submenu" title="Clocker" systemMenu="apple" id="57">
                        <items>
                            <menuItem title="About Clocker" id="58">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="236">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Preferences…" keyEquivalent="," id="129"/>
                            <menuItem isSeparatorItem="YES" id="143">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Services" id="131">
                                <menu key="submenu" title="Services" systemMenu="services" id="130"/>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="144">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Hide Clocker" keyEquivalent="h" id="134">
                                <connections>
                                    <action selector="hide:" target="-1" id="367"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Hide Others" keyEquivalent="h" id="145">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="hideOtherApplications:" target="-1" id="368"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Show All" id="150">
                                <connections>
                                    <action selector="unhideAllApplications:" target="-1" id="370"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="149">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Quit Clocker" keyEquivalent="q" id="136">
                                <connections>
                                    <action selector="terminate:" target="-3" id="449"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="File" id="83">
                    <menu key="submenu" title="File" id="81">
                        <items>
                            <menuItem title="New" keyEquivalent="n" id="82">
                                <connections>
                                    <action selector="newDocument:" target="-1" id="373"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open…" keyEquivalent="o" id="72">
                                <connections>
                                    <action selector="openDocument:" target="-1" id="374"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open Recent" id="124">
                                <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
                                    <items>
                                        <menuItem title="Clear Menu" id="126">
                                            <connections>
                                                <action selector="clearRecentDocuments:" target="-1" id="127"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="79">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Close" keyEquivalent="w" id="73">
                                <connections>
                                    <action selector="performClose:" target="-1" id="193"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Save…" keyEquivalent="s" id="75">
                                <connections>
                                    <action selector="saveDocument:" target="-1" id="362"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Revert to Saved" id="112">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="revertDocumentToSaved:" target="-1" id="364"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="74">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Page Setup..." keyEquivalent="P" id="77">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                <connections>
                                    <action selector="runPageLayout:" target="-1" id="87"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Print…" keyEquivalent="p" id="78">
                                <connections>
                                    <action selector="print:" target="-1" id="86"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Edit" id="217">
                    <menu key="submenu" title="Edit" id="205">
                        <items>
                            <menuItem title="Undo" keyEquivalent="z" id="207">
                                <connections>
                                    <action selector="undo:" target="-1" id="223"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Redo" keyEquivalent="Z" id="215">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                <connections>
                                    <action selector="redo:" target="-1" id="231"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="206">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Cut" keyEquivalent="x" id="199">
                                <connections>
                                    <action selector="cut:" target="-1" id="228"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Copy" keyEquivalent="c" id="197">
                                <connections>
                                    <action selector="copy:" target="-1" id="224"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste" keyEquivalent="v" id="203">
                                <connections>
                                    <action selector="paste:" target="-1" id="226"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste and Match Style" keyEquivalent="v" id="485">
                                <connections>
                                    <action selector="pasteAsPlainText:" target="-1" id="486"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" id="202">
                                <connections>
                                    <action selector="delete:" target="-1" id="235"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Select All" keyEquivalent="a" id="198">
                                <connections>
                                    <action selector="selectAll:" target="-1" id="232"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="214">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Find" id="218">
                                <menu key="submenu" title="Find" id="220">
                                    <items>
                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="241"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="535"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="487"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="488"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="489"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="210">
                                            <connections>
                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Spelling and Grammar" id="216">
                                <menu key="submenu" title="Spelling and Grammar" id="200">
                                    <items>
                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
                                            <connections>
                                                <action selector="showGuessPanel:" target="-1" id="230"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Document Now" keyEquivalent=";" id="201">
                                            <connections>
                                                <action selector="checkSpelling:" target="-1" id="225"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="453"/>
                                        <menuItem title="Check Spelling While Typing" id="219">
                                            <connections>
                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Grammar With Spelling" id="346">
                                            <connections>
                                                <action selector="toggleGrammarChecking:" target="-1" id="347"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Correct Spelling Automatically" id="454">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Substitutions" id="348">
                                <menu key="submenu" title="Substitutions" id="349">
                                    <items>
                                        <menuItem title="Show Substitutions" id="457">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="459"/>
                                        <menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
                                            <connections>
                                                <action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
                                            <connections>
                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Dashes" id="460">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                            <connections>
                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Text Replacement" id="462">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Transformations" id="450">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Transformations" id="451">
                                    <items>
                                        <menuItem title="Make Upper Case" id="452">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="uppercaseWord:" target="-1" id="464"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Make Lower Case" id="465">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="lowercaseWord:" target="-1" id="468"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Capitalize" id="466">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="capitalizeWord:" target="-1" id="467"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Speech" id="211">
                                <menu key="submenu" title="Speech" id="212">
                                    <items>
                                        <menuItem title="Start Speaking" id="196">
                                            <connections>
                                                <action selector="startSpeaking:" target="-1" id="233"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Stop Speaking" id="195">
                                            <connections>
                                                <action selector="stopSpeaking:" target="-1" id="227"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Window" id="19">
                    <menu key="submenu" title="Window" systemMenu="window" id="24">
                        <items>
                            <menuItem title="Minimize" keyEquivalent="m" id="23">
                                <connections>
                                    <action selector="performMiniaturize:" target="-1" id="37"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Zoom" id="239">
                                <connections>
                                    <action selector="performZoom:" target="-1" id="240"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="92">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Bring All to Front" id="5">
                                <connections>
                                    <action selector="arrangeInFront:" target="-1" id="39"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
            </items>
        </menu>
        <customObject id="494" customClass="AppDelegate" customModule="Clocker" customModuleProvider="target"/>
        <customObject id="420" customClass="NSFontManager"/>
    </objects>
</document>


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/.gitignore
================================================
# Xcode
build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.xcworkspace
!default.xcworkspace
xcuserdata
profile
*.moved-aside

## Ignore incredibly annoying .DS_Store files
.DS_Store


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/LICENSE.md
================================================
# ShortcutRecorder

Copyright (c) 2006, Contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the organization nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# PTHotKey

Copyright (c) 2003 Quentin D. Carnicelli.
All rights reserved.


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>ShortcutRecorder</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>2.17</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>2.17</string>
</dict>
</plist>


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/Prefix.pch
================================================

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
    #import <Carbon/Carbon.h>
#endif


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRCommon.h
================================================
//
//  SRCommon.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Andy Kim
//      Ilya Kulakov

#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>


/*!
    Mask representing subset of Cocoa modifier flags suitable for shortcuts.
 */
static const NSEventModifierFlags SRCocoaModifierFlagsMask = NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagControl;

/*!
    Mask representing subset of Carbon modifier flags suitable for shortcuts.
 */
static const NSUInteger SRCarbonModifierFlagsMask = cmdKey | optionKey | shiftKey | controlKey;


/*!
    Converts carbon modifier flags to cocoa.
 */
FOUNDATION_STATIC_INLINE NSEventModifierFlags SRCarbonToCocoaFlags(UInt32 aCarbonFlags)
{
    NSEventModifierFlags cocoaFlags = 0;

    if (aCarbonFlags & cmdKey)
        cocoaFlags |= NSEventModifierFlagCommand;

    if (aCarbonFlags & optionKey)
        cocoaFlags |= NSEventModifierFlagOption;

    if (aCarbonFlags & controlKey)
        cocoaFlags |= NSEventModifierFlagControl;

    if (aCarbonFlags & shiftKey)
        cocoaFlags |= NSEventModifierFlagShift;

    return cocoaFlags;
}

/*!
    Converts cocoa modifier flags to carbon.
 */
FOUNDATION_STATIC_INLINE UInt32 SRCocoaToCarbonFlags(NSEventModifierFlags aCocoaFlags)
{
    UInt32 carbonFlags = 0;

    if (aCocoaFlags & NSEventModifierFlagCommand)
        carbonFlags |= cmdKey;

    if (aCocoaFlags & NSEventModifierFlagOption)
        carbonFlags |= optionKey;

    if (aCocoaFlags & NSEventModifierFlagControl)
        carbonFlags |= controlKey;

    if (aCocoaFlags & NSEventModifierFlagShift)
        carbonFlags |= shiftKey;

    return carbonFlags;
}


/*!
    Return Bundle where resources can be found.

    @discussion Throws NSInternalInconsistencyException if bundle cannot be found.
*/
NSBundle *SRBundle(void);


/*!
    Convenient method to get localized string from the framework bundle.
 */
NSString *SRLoc(NSString *aKey);


/*!
    Convenient method to get image from the framework bundle.
 */
NSImage *SRImage(NSString *anImageName);

/*!
    Returns string representation of shortcut with modifier flags replaced with their localized
    readable equivalents (e.g. ? -> Option).
 */
NSString *SRReadableStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode);

/*!
    Returns string representation of shortcut with modifier flags replaced with their localized
    readable equivalents (e.g. ? -> Option) and ASCII character for key code.
 */
NSString *SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode);

/*!
    Determines if given key code with flags is equal to key equivalent and flags
    (usually taken from NSButton or NSMenu).

    @discussion On Mac OS X some key combinations can have "alternates". E.g. option-A can be represented both as option-A and as .
*/
BOOL SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(unsigned short aKeyCode,
                                                     NSEventModifierFlags aKeyCodeFlags,
                                                     NSString *aKeyEquivalent,
                                                     NSEventModifierFlags aKeyEquivalentModifierFlags);


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRCommon.m
================================================
//
//  SRCommon.m
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Andy Kim
//      Ilya Kulakov

#import "SRCommon.h"
#import "SRKeyCodeTransformer.h"


NSBundle *SRBundle(void)
{
    static dispatch_once_t onceToken;
    static NSBundle *Bundle = nil;
    dispatch_once(&onceToken, ^{
        Bundle = [NSBundle bundleWithIdentifier:@"com.kulakov.ShortcutRecorder"];

        if (!Bundle)
        {
            // Could be a CocoaPods framework with embedded resources bundle.
            // Look up "use_frameworks!" and "resources_bundle" in CocoaPods documentation.
            Bundle = [NSBundle bundleWithIdentifier:@"org.cocoapods.ShortcutRecorder"];

            if (!Bundle)
            {
                Class c = NSClassFromString(@"SRRecorderControl");

                if (c)
                {
                    Bundle = [NSBundle bundleForClass:c];
                }
            }

            if (Bundle)
            {
                Bundle = [NSBundle bundleWithPath:[Bundle pathForResource:@"ShortcutRecorder" ofType:@"bundle"]];
            }
        }
    });

    if (!Bundle)
    {
        @throw [NSException exceptionWithName:NSInternalInconsistencyException
                                       reason:@"Unable to find bundle with resources."
                                     userInfo:nil];
    }
    else
    {
        return Bundle;
    }
}


NSString *SRLoc(NSString *aKey)
{
    return NSLocalizedStringFromTableInBundle(aKey, @"ShortcutRecorder", SRBundle(), nil);
}


NSImage *SRImage(NSString *anImageName)
{
    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6)
        return [[NSImage alloc] initByReferencingURL:[SRBundle() URLForImageResource:anImageName]];
    else
        return [SRBundle() imageForResource:anImageName];
}


NSString *SRReadableStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode)
{
    SRKeyCodeTransformer *t = [SRKeyCodeTransformer sharedPlainTransformer];
    NSString *c = [t transformedValue:@(aKeyCode)];

    return [NSString stringWithFormat:@"%@%@%@%@%@",
            (aModifierFlags & NSEventModifierFlagCommand ? SRLoc(@"Command-") : @""),
            (aModifierFlags & NSEventModifierFlagOption ? SRLoc(@"Option-") : @""),
            (aModifierFlags & NSEventModifierFlagControl ? SRLoc(@"Control-") : @""),
            (aModifierFlags & NSEventModifierFlagShift ? SRLoc(@"Shift-") : @""),
                                      c];
}


NSString *SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode)
{
    SRKeyCodeTransformer *t = [SRKeyCodeTransformer sharedPlainASCIITransformer];
    NSString *c = [t transformedValue:@(aKeyCode)];

    return [NSString stringWithFormat:@"%@%@%@%@%@",
            (aModifierFlags & NSEventModifierFlagCommand ? SRLoc(@"Command-") : @""),
            (aModifierFlags & NSEventModifierFlagOption ? SRLoc(@"Option-") : @""),
            (aModifierFlags & NSEventModifierFlagControl ? SRLoc(@"Control-") : @""),
            (aModifierFlags & NSEventModifierFlagShift ? SRLoc(@"Shift-") : @""),
            c];
}


static BOOL _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(unsigned short aKeyCode,
                                                             NSEventModifierFlags aKeyCodeFlags,
                                                             NSString *aKeyEquivalent,
                                                             NSEventModifierFlags aKeyEquivalentModifierFlags,
                                                             SRKeyCodeTransformer *aTransformer)
{
    if (!aKeyEquivalent)
        return NO;

    aKeyCodeFlags &= SRCocoaModifierFlagsMask;
    aKeyEquivalentModifierFlags &= SRCocoaModifierFlagsMask;

    if (aKeyCodeFlags == aKeyEquivalentModifierFlags)
    {
        NSString *keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
                                               withImplicitModifierFlags:nil
                                                   explicitModifierFlags:@(aKeyCodeFlags)];
        return [keyCodeRepresentation isEqual:aKeyEquivalent];
    }
    else if (!aKeyEquivalentModifierFlags ||
             (aKeyCodeFlags & aKeyEquivalentModifierFlags) == aKeyEquivalentModifierFlags)
    {
        // Some key equivalent modifier flags can be implicitly set by using special unicode characters. E.g.  insetead of opt-a.
        // However all modifier flags explictily set in key equivalent MUST be also set in key code flags.
        // E.g. ctrl-/ctrl-opt-a and /opt-a match this condition, but cmd-/ctrl-opt-a doesn't.
        NSString *keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
                                               withImplicitModifierFlags:nil
                                                   explicitModifierFlags:@(aKeyCodeFlags)];

        if ([keyCodeRepresentation isEqual:aKeyEquivalent])
        {
            // Key code and key equivalent are not equal key code representation matches key equivalent, but modifier flags are not.
            return NO;
        }
        else
        {
            NSEventModifierFlags possiblyImplicitFlags = aKeyCodeFlags & ~aKeyEquivalentModifierFlags;
            keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
                                         withImplicitModifierFlags:@(possiblyImplicitFlags)
                                             explicitModifierFlags:@(aKeyEquivalentModifierFlags)];
            return [keyCodeRepresentation isEqual:aKeyEquivalent];
        }
    }
    else
        return NO;
}


BOOL SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(unsigned short aKeyCode,
                                                     NSEventModifierFlags aKeyCodeFlags,
                                                     NSString *aKeyEquivalent,
                                                     NSEventModifierFlags aKeyEquivalentModifierFlags)
{
    BOOL isEqual = _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(aKeyCode,
                                                                    aKeyCodeFlags,
                                                                    aKeyEquivalent,
                                                                    aKeyEquivalentModifierFlags,
                                                                    [SRKeyCodeTransformer sharedASCIITransformer]);

    if (!isEqual)
    {
        isEqual = _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(aKeyCode,
                                                                   aKeyCodeFlags,
                                                                   aKeyEquivalent,
                                                                   aKeyEquivalentModifierFlags,
                                                                   [SRKeyCodeTransformer sharedTransformer]);
    }

    return isEqual;
}


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyCodeTransformer.h
================================================
//
//  SRKeyCodeTransformer.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Ilya Kulakov
//      Silvio Rizzi

#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>


/*!
    Transforms key code into unicode character or plain string.
 */
@interface SRKeyCodeTransformer : NSValueTransformer

/*!
    Returns initialized key code transformer.

    @param      aUsesASCII Determines whether transformer uses only ASCII capable keyboard input source.

    @param      aUsesPlainStrings Determines whether key codes without readable glyphs (e.g. F1...F19) are transformed to
                to unicode characters (NSF1FunctionKey...NSF19FunctionKey) suitable for setting key equivalents
                of Cocoa controls or to plain strings (@"F1"...@"F19") suitable for drawing, logging and accessibility.

    @discussion This method is the designated initializer for SRKeyCodeTransformer.
 */
- (instancetype)initWithASCIICapableKeyboardInputSource:(BOOL)aUsesASCII plainStrings:(BOOL)aUsesPlainStrings;

/*!
    Determines whether transformer uses ASCII capable keyboard input source.
 */
@property (readonly) BOOL usesASCIICapableKeyboardInputSource;

/*!
    Determines whether key codes without readable glyphs are transformed to unicode characters
    suitable for setting keqEquivalents or to plain strings suitable for drawing, logging and accessibility.
 */
@property (readonly) BOOL usesPlainStrings;

/*!
    Returns the shared transformer.
 */
+ (instancetype)sharedTransformer;

/*!
    Returns the shared transformer configured to use only ASCII capable keyboard input source.
 */
+ (instancetype)sharedASCIITransformer;

/*!
    Returns the shared transformer configured to transform key codes to plain strings.
 */
+ (SRKeyCodeTransformer *)sharedPlainTransformer;

/*!
    Returns the shared transformer configured to use only ASCII capable keyboard input source
            and to transform key codes to plain strings.
 */
+ (SRKeyCodeTransformer *)sharedPlainASCIITransformer;


/*!
    Returns mapping from special key codes to unicode characters.
 */
+ (NSDictionary *)specialKeyCodesToUnicodeCharactersMapping;

/*!
    Returns mapping from special key codes to plain strings.
 */
+ (NSDictionary *)specialKeyCodesToPlainStringsMapping;

/*!
    Determines whether key code is special.

    @param  aKeyCode Key code to be checked.
 */
- (BOOL)isKeyCodeSpecial:(unsigned short)aKeyCode;

/*!
    Transforms given special key code into unicode character by taking into account modifier flags.
 
    @discussion E.g. the key code 0x30 is transformed to ⇥. But if shift is pressed, it is transformed to ⇤.
 
    @result     Unicode character or plain string. nil if not a special key code.
*/
- (NSString *)transformedSpecialKeyCode:(NSNumber *)aKeyCode withExplicitModifierFlags:(NSNumber *)aModifierFlags;

/*!
    Shorcut to [self transformedValue:aValue withImplicitModifierFlags:aModifierFlags explicitModifierFlags:0]
 */
- (NSString *)transformedValue:(NSNumber *)aValue withModifierFlags:(NSNumber *)aModifierFlags;

/*!
    Transfroms given key code into unicode character by taking into account modifier flags.
 
    @param  aValue An instance of NSNumber (unsigned short) that represents key code.
 
    @param  anImplicitModifierFlags An instance of NSNumber (NSEventModifierFlags) that represents implicit modifier flags like opt in å.
 
    @param  anExplicitModifierFlags An instance of NSNumber (NSEventModifierFlags) that represents explicit modifier flags like shift in shift-⇤.
 */
- (NSString *)transformedValue:(NSNumber *)aValue withImplicitModifierFlags:(NSNumber *)anImplicitModifierFlags explicitModifierFlags:(NSNumber *)anExplicitModifierFlags;

@end


/*!
    These constants represents drawable unicode characters for key codes that do not have
    appropriate constants in Carbon and Cocoa.
 */
typedef NS_ENUM(unichar, SRKeyCodeGlyph)
{
    SRKeyCodeGlyphTabRight = 0x21E5, // ⇥
    SRKeyCodeGlyphTabLeft = 0x21E4, // ⇤
    SRKeyCodeGlyphReturn = 0x2305, // ⌅
    SRKeyCodeGlyphReturnR2L = 0x21A9, // ↩
    SRKeyCodeGlyphDeleteLeft = 0x232B, // ⌫
    SRKeyCodeGlyphDeleteRight = 0x2326, // ⌦
    SRKeyCodeGlyphPadClear = 0x2327, // ⌧
    SRKeyCodeGlyphLeftArrow = 0x2190, // ←
    SRKeyCodeGlyphRightArrow = 0x2192, // →
    SRKeyCodeGlyphUpArrow = 0x2191, // ↑
    SRKeyCodeGlyphDownArrow = 0x2193, // ↓
    SRKeyCodeGlyphPageDown = 0x21DF, // ⇟
    SRKeyCodeGlyphPageUp = 0x21DE, // ⇞
    SRKeyCodeGlyphNorthwestArrow = 0x2196, // ↖
    SRKeyCodeGlyphSoutheastArrow = 0x2198, // ↘
    SRKeyCodeGlyphEscape = 0x238B, // ⎋
    SRKeyCodeGlyphSpace = 0x0020, // ' '
};


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyCodeTransformer.m
================================================
//
//  SRKeyCodeTransformer.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Ilya Kulakov
//      Silvio Rizzi

#import "SRKeyCodeTransformer.h"
#import "SRCommon.h"


FOUNDATION_STATIC_INLINE NSString* _SRUnicharToString(unichar aChar)
{
    return [NSString stringWithFormat: @"%C", aChar];
}


@implementation SRKeyCodeTransformer

- (instancetype)initWithASCIICapableKeyboardInputSource:(BOOL)aUsesASCII plainStrings:(BOOL)aUsesPlainStrings
{
    self = [super init];

    if (self)
    {
        _usesASCIICapableKeyboardInputSource = aUsesASCII;
        _usesPlainStrings = aUsesPlainStrings;
    }

    return self;
}

- (instancetype)init
{
    return [self initWithASCIICapableKeyboardInputSource:NO plainStrings:NO];
}


#pragma mark Methods

+ (instancetype)sharedTransformer
{
    static dispatch_once_t OnceToken;
    static SRKeyCodeTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithASCIICapableKeyboardInputSource:NO
                                                               plainStrings:NO];
    });
    return Transformer;
}

+ (instancetype)sharedASCIITransformer
{
    static dispatch_once_t OnceToken;
    static SRKeyCodeTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithASCIICapableKeyboardInputSource:YES
                                                               plainStrings:NO];
    });
    return Transformer;
}

+ (instancetype)sharedPlainTransformer
{
    static dispatch_once_t OnceToken;
    static SRKeyCodeTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithASCIICapableKeyboardInputSource:NO
                                                               plainStrings:YES];
    });
    return Transformer;
}

+ (SRKeyCodeTransformer *)sharedPlainASCIITransformer
{
    static dispatch_once_t OnceToken;
    static SRKeyCodeTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithASCIICapableKeyboardInputSource:YES
                                                               plainStrings:YES];
    });
    return Transformer;
}

+ (NSDictionary *)specialKeyCodesToUnicodeCharactersMapping
{
    // Most of these keys are system constans.
    // Values for rest of the keys were given by setting key equivalents in IB.
    static dispatch_once_t OnceToken;
    static NSDictionary *Mapping = nil;
    dispatch_once(&OnceToken, ^{
        Mapping = @{
            @(kVK_F1): _SRUnicharToString(NSF1FunctionKey),
            @(kVK_F2): _SRUnicharToString(NSF2FunctionKey),
            @(kVK_F3): _SRUnicharToString(NSF3FunctionKey),
            @(kVK_F4): _SRUnicharToString(NSF4FunctionKey),
            @(kVK_F5): _SRUnicharToString(NSF5FunctionKey),
            @(kVK_F6): _SRUnicharToString(NSF6FunctionKey),
            @(kVK_F7): _SRUnicharToString(NSF7FunctionKey),
            @(kVK_F8): _SRUnicharToString(NSF8FunctionKey),
            @(kVK_F9): _SRUnicharToString(NSF9FunctionKey),
            @(kVK_F10): _SRUnicharToString(NSF10FunctionKey),
            @(kVK_F11): _SRUnicharToString(NSF11FunctionKey),
            @(kVK_F12): _SRUnicharToString(NSF12FunctionKey),
            @(kVK_F13): _SRUnicharToString(NSF13FunctionKey),
            @(kVK_F14): _SRUnicharToString(NSF14FunctionKey),
            @(kVK_F15): _SRUnicharToString(NSF15FunctionKey),
            @(kVK_F16): _SRUnicharToString(NSF16FunctionKey),
            @(kVK_F17): _SRUnicharToString(NSF17FunctionKey),
            @(kVK_F18): _SRUnicharToString(NSF18FunctionKey),
            @(kVK_F19): _SRUnicharToString(NSF19FunctionKey),
            @(kVK_F20): _SRUnicharToString(NSF20FunctionKey),
            @(kVK_Space): _SRUnicharToString(' '),
            @(kVK_Delete): _SRUnicharToString(NSBackspaceCharacter),
            @(kVK_ForwardDelete): _SRUnicharToString(NSDeleteCharacter),
            @(kVK_ANSI_KeypadClear): _SRUnicharToString(NSClearLineFunctionKey),
            @(kVK_LeftArrow): _SRUnicharToString(NSLeftArrowFunctionKey),
            @(kVK_RightArrow): _SRUnicharToString(NSRightArrowFunctionKey),
            @(kVK_UpArrow): _SRUnicharToString(NSUpArrowFunctionKey),
            @(kVK_DownArrow): _SRUnicharToString(NSDownArrowFunctionKey),
            @(kVK_End): _SRUnicharToString(NSEndFunctionKey),
            @(kVK_Home): _SRUnicharToString(NSHomeFunctionKey),
            @(kVK_Escape): _SRUnicharToString('\e'),
            @(kVK_PageDown): _SRUnicharToString(NSPageDownFunctionKey),
            @(kVK_PageUp): _SRUnicharToString(NSPageUpFunctionKey),
            @(kVK_Return): _SRUnicharToString(NSCarriageReturnCharacter),
            @(kVK_ANSI_KeypadEnter): _SRUnicharToString(NSEnterCharacter),
            @(kVK_Tab): _SRUnicharToString(NSTabCharacter),
            @(kVK_Help): _SRUnicharToString(NSHelpFunctionKey)
        };
    });
    return Mapping;
}

+ (NSDictionary *)specialKeyCodesToPlainStringsMapping
{
    static dispatch_once_t OnceToken;
    static NSDictionary *Mapping = nil;
    dispatch_once(&OnceToken, ^{
        Mapping = @{
            @(kVK_F1): @"F1",
            @(kVK_F2): @"F2",
            @(kVK_F3): @"F3",
            @(kVK_F4): @"F4",
            @(kVK_F5): @"F5",
            @(kVK_F6): @"F6",
            @(kVK_F7): @"F7",
            @(kVK_F8): @"F8",
            @(kVK_F9): @"F9",
            @(kVK_F10): @"F10",
            @(kVK_F11): @"F11",
            @(kVK_F12): @"F12",
            @(kVK_F13): @"F13",
            @(kVK_F14): @"F14",
            @(kVK_F15): @"F15",
            @(kVK_F16): @"F16",
            @(kVK_F17): @"F17",
            @(kVK_F18): @"F18",
            @(kVK_F19): @"F19",
            @(kVK_F20): @"F20",
            @(kVK_Space): SRLoc(@"Space"),
            @(kVK_Delete): _SRUnicharToString(SRKeyCodeGlyphDeleteLeft),
            @(kVK_ForwardDelete): _SRUnicharToString(SRKeyCodeGlyphDeleteRight),
            @(kVK_ANSI_KeypadClear): _SRUnicharToString(SRKeyCodeGlyphPadClear),
            @(kVK_LeftArrow): _SRUnicharToString(SRKeyCodeGlyphLeftArrow),
            @(kVK_RightArrow): _SRUnicharToString(SRKeyCodeGlyphRightArrow),
            @(kVK_UpArrow): _SRUnicharToString(SRKeyCodeGlyphUpArrow),
            @(kVK_DownArrow): _SRUnicharToString(SRKeyCodeGlyphDownArrow),
            @(kVK_End): _SRUnicharToString(SRKeyCodeGlyphSoutheastArrow),
            @(kVK_Home): _SRUnicharToString(SRKeyCodeGlyphNorthwestArrow),
            @(kVK_Escape): _SRUnicharToString(SRKeyCodeGlyphEscape),
            @(kVK_PageDown): _SRUnicharToString(SRKeyCodeGlyphPageDown),
            @(kVK_PageUp): _SRUnicharToString(SRKeyCodeGlyphPageUp),
            @(kVK_Return): _SRUnicharToString(SRKeyCodeGlyphReturnR2L),
            @(kVK_ANSI_KeypadEnter): _SRUnicharToString(SRKeyCodeGlyphReturn),
            @(kVK_Tab): _SRUnicharToString(SRKeyCodeGlyphTabRight),
            @(kVK_Help): @"?⃝"
        };
    });
    return Mapping;
}

- (BOOL)isKeyCodeSpecial:(unsigned short)aKeyCode
{
    switch (aKeyCode)
    {
        case kVK_F1:
        case kVK_F2:
        case kVK_F3:
        case kVK_F4:
        case kVK_F5:
        case kVK_F6:
        case kVK_F7:
        case kVK_F8:
        case kVK_F9:
        case kVK_F10:
        case kVK_F11:
        case kVK_F12:
        case kVK_F13:
        case kVK_F14:
        case kVK_F15:
        case kVK_F16:
        case kVK_F17:
        case kVK_F18:
        case kVK_F19:
        case kVK_F20:
        case kVK_Space:
        case kVK_Delete:
        case kVK_ForwardDelete:
        case kVK_ANSI_KeypadClear:
        case kVK_LeftArrow:
        case kVK_RightArrow:
        case kVK_UpArrow:
        case kVK_DownArrow:
        case kVK_End:
        case kVK_Home:
        case kVK_Escape:
        case kVK_PageDown:
        case kVK_PageUp:
        case kVK_Return:
        case kVK_ANSI_KeypadEnter:
        case kVK_Tab:
        case kVK_Help:
            return YES;
        default:
            return NO;
    }
}


#pragma mark NSValueTransformer

+ (BOOL)allowsReverseTransformation
{
    return NO;
}

+ (Class)transformedValueClass;
{
    return [NSString class];
}

- (NSString *)transformedValue:(NSNumber *)aValue
{
    return [self transformedValue:aValue withModifierFlags:nil];
}

- (NSString *)transformedValue:(NSNumber *)aValue withModifierFlags:(NSNumber *)aModifierFlags
{
    return [self transformedValue:aValue withImplicitModifierFlags:aModifierFlags explicitModifierFlags:nil];
}

- (NSString *)transformedValue:(NSNumber *)aValue withImplicitModifierFlags:(NSNumber *)anImplicitModifierFlags explicitModifierFlags:(NSNumber *)anExplicitModifierFlags
{
    if ([anImplicitModifierFlags unsignedIntegerValue] & [anExplicitModifierFlags unsignedIntegerValue] & SRCocoaModifierFlagsMask)
    {
        [NSException raise:NSInvalidArgumentException format:@"anImplicitModifierFlags and anExplicitModifierFlags MUST NOT have common elements"];
    }

    if (![aValue isKindOfClass:[NSNumber class]])
        return @"";

    // Some key codes cannot be translated directly.
    NSString *unmappedString = [self transformedSpecialKeyCode:aValue withExplicitModifierFlags:anExplicitModifierFlags];

    if (unmappedString)
        return unmappedString;

    CFDataRef layoutData = NULL;

    if (self.usesASCIICapableKeyboardInputSource)
    {
        TISInputSourceRef tisSource = TISCopyCurrentASCIICapableKeyboardLayoutInputSource();

        if (!tisSource)
            return @"";

        layoutData = (CFDataRef)TISGetInputSourceProperty(tisSource, kTISPropertyUnicodeKeyLayoutData);
        CFRelease(tisSource);
    }
    else
    {
        TISInputSourceRef tisSource = TISCopyCurrentKeyboardLayoutInputSource();

        if (!tisSource)
            return @"";

        layoutData = (CFDataRef)TISGetInputSourceProperty(tisSource, kTISPropertyUnicodeKeyLayoutData);
        CFRelease(tisSource);

        // For non-unicode layouts such as Chinese, Japanese, and Korean, get the ASCII capable layout
        if (!layoutData)
        {
            tisSource = TISCopyCurrentASCIICapableKeyboardLayoutInputSource();

            if (!tisSource)
                return @"";

            layoutData = (CFDataRef)TISGetInputSourceProperty(tisSource, kTISPropertyUnicodeKeyLayoutData);
            CFRelease(tisSource);
        }
    }

    if (!layoutData)
        return @"";

    const UCKeyboardLayout *keyLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);

    static const UniCharCount MaxLength = 255;
    UniCharCount actualLength = 0;
    UniChar chars[MaxLength] = {0};

    UInt32 deadKeyState = 0;
    OSStatus err = UCKeyTranslate(keyLayout,
                                  [aValue unsignedShortValue],
                                  kUCKeyActionDisplay,
                                  SRCocoaToCarbonFlags([anImplicitModifierFlags unsignedIntegerValue]) >> 8,
                                  LMGetKbdType(),
                                  kUCKeyTranslateNoDeadKeysBit,
                                  &deadKeyState,
                                  sizeof(chars) / sizeof(UniChar),
                                  &actualLength,
                                  chars);
    if (err != noErr)
        return @"";

    if (self.usesPlainStrings)
        return [[NSString stringWithCharacters:chars length:actualLength] uppercaseString];
    else
        return [NSString stringWithCharacters:chars length:actualLength];
}

- (NSString *)transformedSpecialKeyCode:(NSNumber *)aKeyCode withExplicitModifierFlags:(NSNumber *)anExplicitModifierFlags
{
    if ([anExplicitModifierFlags unsignedIntegerValue] & NSEventModifierFlagShift && [aKeyCode unsignedShortValue] == kVK_Tab)
    {
        if (self.usesPlainStrings)
            return _SRUnicharToString(SRKeyCodeGlyphTabLeft);
        else
            return _SRUnicharToString(NSBackTabCharacter);
    }

    if (self.usesPlainStrings)
        return [[self class] specialKeyCodesToPlainStringsMapping][aKeyCode];
    else
        return [[self class] specialKeyCodesToUnicodeCharactersMapping][aKeyCode];
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentModifierMaskTransformer.h
================================================
//
//  SRKeyEquivalentModifierMaskTransformer.h
//  ShortcutRecorder
//
//  Copyright 2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors to this file:
//      Ilya Kulakov

#import <Foundation/Foundation.h>


/*!
    Transform dictionary representation of shortcut into string suitable
    for -setKeyEquivalentModifierMask: of NSButton and NSMenuItem.
 */
@interface SRKeyEquivalentModifierMaskTransformer : NSValueTransformer

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentModifierMaskTransformer.m
================================================
//
//  SRKeyEquivalentModifierMaskTransformer.m
//  ShortcutRecorder
//
//  Copyright 2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      Ilya Kulakov

#import "SRKeyEquivalentModifierMaskTransformer.h"
#import "SRKeyCodeTransformer.h"
#import "SRRecorderControl.h"


@implementation SRKeyEquivalentModifierMaskTransformer

#pragma mark NSValueTransformer

+ (BOOL)allowsReverseTransformation
{
    return NO;
}

+ (Class)transformedValueClass
{
    return [NSNumber class];
}

- (NSNumber *)transformedValue:(NSDictionary *)aValue
{
    if (![aValue isKindOfClass:[NSDictionary class]])
        return @(0);

    NSNumber *modifierFlags = aValue[SRShortcutModifierFlagsKey];

    if (![modifierFlags isKindOfClass:[NSNumber class]])
        return @(0);

    return modifierFlags;
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentTransformer.h
================================================
//
//  SRKeyEquivalentTransformer.h
//  ShortcutRecorder
//
//  Copyright 2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors to this file:
//      Ilya Kulakov

#import <Foundation/Foundation.h>


/*!
    Transform dictionary representation of shortcut into string suitable
    for -setKeyEquivalent: of NSButton and NSMenuItem.
 */
@interface SRKeyEquivalentTransformer : NSValueTransformer

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentTransformer.m
================================================
//
//  SRKeyEquivalentTransformer.m
//  ShortcutRecorder
//
//  Copyright 2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      Ilya Kulakov

#import "SRKeyEquivalentTransformer.h"
#import "SRKeyCodeTransformer.h"
#import "SRRecorderControl.h"


@implementation SRKeyEquivalentTransformer

#pragma mark NSValueTransformer

+ (BOOL)allowsReverseTransformation
{
    return NO;
}

+ (Class)transformedValueClass
{
    return [NSString class];
}

- (NSString *)transformedValue:(NSDictionary *)aValue
{
    if (![aValue isKindOfClass:[NSDictionary class]])
        return @"";

    NSNumber *keyCode = aValue[SRShortcutKeyCode];

    if (![keyCode isKindOfClass:[NSNumber class]])
        return @"";

    NSNumber *modifierFlags = aValue[SRShortcutModifierFlagsKey];

    if (![modifierFlags isKindOfClass:[NSNumber class]])
        modifierFlags = @(0);

    SRKeyCodeTransformer *t = [SRKeyCodeTransformer sharedASCIITransformer];

    return [t transformedValue:keyCode
     withImplicitModifierFlags:nil
         explicitModifierFlags:modifierFlags];
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRModifierFlagsTransformer.h
================================================
//
//  SRModifierFlagsTransformer.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      Ilya Kulakov

#import <Cocoa/Cocoa.h>


/*!
    Transforms mask of Cocoa modifier flags to string of unicode characters.
 */
@interface SRModifierFlagsTransformer : NSValueTransformer

- (instancetype)initWithPlainStrings:(BOOL)aUsesPlainStrings;

/*!
    Determines whether modifier flags are transformed to unicode characters or to plain strings.
 */
@property (readonly) BOOL usesPlainStrings;

/*!
     Returns the shared transformer.
 */
+ (instancetype)sharedTransformer;

/*!
     Returns the shared plain transformer.
 */
+ (instancetype)sharedPlainTransformer;

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRModifierFlagsTransformer.m
================================================
//
//  SRModifierFlagsTransformer.m
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      Ilya Kulakov

#import "SRModifierFlagsTransformer.h"
#import "SRCommon.h"


@implementation SRModifierFlagsTransformer

- (instancetype)initWithPlainStrings:(BOOL)aUsesPlainStrings
{
    self = [super init];

    if (self)
    {
        _usesPlainStrings = aUsesPlainStrings;
    }

    return self;
}

- (instancetype)init
{
    return [self initWithPlainStrings:NO];
}


#pragma mark Methods

+ (instancetype)sharedTransformer
{
    static dispatch_once_t OnceToken;
    static SRModifierFlagsTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithPlainStrings:NO];
    });
    return Transformer;
}

+ (instancetype)sharedPlainTransformer
{
    static dispatch_once_t OnceToken;
    static SRModifierFlagsTransformer *Transformer = nil;
    dispatch_once(&OnceToken, ^{
        Transformer = [[self alloc] initWithPlainStrings:YES];
    });
    return Transformer;
}


#pragma mark NSValueTransformer

+ (Class)transformedValueClass
{
    return [NSString class];
}

+ (BOOL)allowsReverseTransformation
{
    return NO;
}

- (NSString *)transformedValue:(NSNumber *)aValue
{
    if (![aValue isKindOfClass:[NSNumber class]])
        return nil;
    else if (self.usesPlainStrings)
    {
        NSEventModifierFlags modifierFlags = [aValue unsignedIntegerValue];
        NSMutableString *s = [NSMutableString string];

        if (modifierFlags & NSEventModifierFlagControl)
            [s appendString:SRLoc(@"Control-")];

        if (modifierFlags & NSEventModifierFlagOption)
            [s appendString:SRLoc(@"Option-")];

        if (modifierFlags & NSEventModifierFlagShift)
            [s appendString:SRLoc(@"Shift-")];

        if (modifierFlags & NSEventModifierFlagCommand)
            [s appendString:SRLoc(@"Command-")];

        if (s.length > 0)
            [s deleteCharactersInRange:NSMakeRange(s.length - 1, 1)];

        return s;
    }
    else
    {
        NSEventModifierFlags f = [aValue unsignedIntegerValue];
        return [NSString stringWithFormat:@"%@%@%@%@",
                (f & NSEventModifierFlagControl ? @"⌃" : @""),
                (f & NSEventModifierFlagOption ? @"⌥" : @""),
                (f & NSEventModifierFlagShift ? @"⇧" : @""),
                (f & NSEventModifierFlagCommand ? @"⌘" : @"")];
    }
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRRecorderControl.h
================================================
//
//  SRRecorderControl.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Ilya Kulakov

#import <Cocoa/Cocoa.h>
#import <ShortcutRecorder/SRCommon.h>


/*!
    Key code.

    @discussion NSNumber representation of unsigned short.
                Required key of SRRecorderControl's objectValue.
 */
extern NSString *const SRShortcutKeyCode;

/*!
    Modifier flags.

    @discussion NSNumber representation of NSEventModifierFlags.
                Optional key of SRRecorderControl's objectValue.
 */
extern NSString *const SRShortcutModifierFlagsKey;

/*!
    Interpretation of key code and modifier flags depending on system locale and input source
    used when shortcut was taken.

    @discussion NSString.
                Optional key of SRRecorderControl's objectValue.
 */
extern NSString *const SRShortcutCharacters;

/*!
    Interpretation of key code without modifier flags depending on system locale and input source
    used when shortcut was taken.

    @discussion NSString.
                Optional key of SRRecorderControl's objectValue.
 */
extern NSString *const SRShortcutCharactersIgnoringModifiers;


@protocol SRRecorderControlDelegate;


/*!
    An SRRecorderControl object is a control (but not a subclass of NSControl) that allows you to record shortcuts.

    @discussion In addition to NSView bindings, exposes:
                NSValueBinding. This binding supports 2 options:
                    - NSValueTransformerBindingOption
                    - NSValueTransformerNameBindingOption
                NSEnabledBinding. This binding supports 2 options:
                    - NSValueTransformerBindingOption
                    - NSValueTransformerNameBindingOption
                    Note that at that moment, this binding _is not_ multivalue.

                Required height: 25 points
                Recommended min width: 100 points
 */
IB_DESIGNABLE
@interface SRRecorderControl : NSView /* <NSAccessibility, NSKeyValueBindingCreation, NSToolTipOwner, NSNibAwaking> */

/*!
    The receiver’s delegate.

    @discussion A recorder control delegate responds to editing-related messages. You can use to to prevent editing
                in some cases or to validate typed shortcuts.
 */
@property (assign) IBOutlet NSObject<SRRecorderControlDelegate> *delegate;

/*!
    Returns an integer bit field indicating allowed modifier flags.

    @discussion Defaults to SRCocoaModifierFlagsMask.
 */
@property (readonly) IBInspectable NSEventModifierFlags allowedModifierFlags;

/*!
    Returns an integer bit field indicating required modifier flags.

    @discussion Defaults to 0.
 */
@property (readonly) IBInspectable NSEventModifierFlags requiredModifierFlags;

/*!
    Determines whether shortcuts without modifier flags are allowed.

    @discussion Defaults to NO.
 */
@property (readonly) IBInspectable BOOL allowsEmptyModifierFlags;

/*!
    Determines whether the control reinterpret key code and modifier flags
    using ASCII capable input source.

    @discussion Defaults to YES.
                If not set, the same key code may be draw differently depending on current input source.
                E.g. with US English input source key code 0x0 is interpreted as "a",
                however with Russian input source, it's interpreted as "ф".
 */
@property IBInspectable BOOL drawsASCIIEquivalentOfShortcut;

/*!
    Determines whether Escape is used to cancel recording.

    @discussion Defaults to YES.
                If set, Escape without modifier flags cannot be recorded as shortcut.
 */
@property IBInspectable BOOL allowsEscapeToCancelRecording;

/*!
    Determines whether delete (or forward delete) is used to remove current shortcut and end recording.

    @discussion Defaults to YES.
                If set, neither Delete nor Forward Delete without modifier flags can be recorded as shortcut.
 */
@property IBInspectable BOOL allowsDeleteToClearShortcutAndEndRecording;

/*!
    Determines whether control enabled and can be edited or not.

    @discussion Defaults to YES.
 */
@property (nonatomic, getter=isEnabled) IBInspectable BOOL enabled;

/*!
    Determines whether recording is in process.
 */
@property (nonatomic, readonly) BOOL isRecording;

/*!
    Returns dictionary representation of receiver's shortcut.
 */
@property (nonatomic, copy) NSDictionary *objectValue;

/*!
    Configures recording behavior of the control.

    @param      newAllowedModifierFlags New allowed modifier flags.

    @param      newRequiredModifierFlags New required modifier flags.

    @param      newAllowsEmptyModifierFlags Determines whether empty modifier flags are allowed.

    @discussion Flags are filtered using SRCocoaModifierFlagsMask. Flags does not affect object values set manually.

                These restrictions can be ignored if delegate implements shortcutRecorder:shouldUnconditionallyAllowModifierFlags:forKeyCode: and returns YES for given modifier flags and key code.

                Throws NSInvalidArgumentException if either required flags are not allowed
                or required flags are not empty and no modifier flags are allowed.

    @see        SRRecorderControlDelegate
 */
- (void)setAllowedModifierFlags:(NSEventModifierFlags)newAllowedModifierFlags
          requiredModifierFlags:(NSEventModifierFlags)newRequiredModifierFlags
       allowsEmptyModifierFlags:(BOOL)newAllowsEmptyModifierFlags;

/*!
    Called to initialize internal state after either initWithFrame or awakeFromNib is called.
 */
- (void)_initInternalState;

/*!
    Turns on the recording mode.

    @discussion You SHOULD not call this method directly.
 */
- (BOOL)beginRecording;

/*!
    Turns off the recording mode. Current object value is preserved.

    @discussion You SHOULD not call this method directly.
 */
- (void)endRecording;

/*!
    Clears object value and turns off the recording mode.

    @discussion You SHOULD not call this method directly.
 */
- (void)clearAndEndRecording;

/*!
    Designated method to end recording. Sets a given object value, updates bindings and turns off the recording mode.

    @discussion You SHOULD not call this method directly.
 */
- (void)endRecordingWithObjectValue:(NSDictionary *)anObjectValue;


/*!
    Returns shape of the control.

    @discussion Primarily used to draw appropriate focus ring.
 */
- (NSBezierPath *)controlShape;

/*!
    Returns rect for label with given attributes.

    @param  aLabel Label for drawing.

    @param  anAttributes A dictionary of NSAttributedString text attributes to be applied to the string.
 */
- (NSRect)rectForLabel:(NSString *)aLabel withAttributes:(NSDictionary *)anAttributes;

/*!
    Returns rect of the snap back button in the receiver coordinates.
 */
- (NSRect)snapBackButtonRect;

/*!
    Returns rect of the clear button in the receiver coordinates.

    @discussion Returned rect will have empty width (other values will be valid) if button should not be drawn.
 */
- (NSRect)clearButtonRect;


/*!
    Returns label to be displayed by the receiver.

    @discussion Returned value depends on isRecording state objectValue and currenlty pressed keys and modifier flags.
 */
- (NSString *)label;

/*!
    Returns label for accessibility.

    @discussion Returned value depends on isRecording state objectValue and currenlty pressed keys and modifier flags.
 */
- (NSString *)accessibilityLabel;

/*!
    Returns string representation of object value.
 */
- (NSString *)stringValue;

/*!
    Returns string representation of object value for accessibility.
 */
- (NSString *)accessibilityStringValue;

/*!
    Returns attirbutes of label to be displayed by the receiver according to current state.

    @see        normalLabelAttributes

    @see        recordingLabelAttributes

    @see        disabledLabelAttributes
 */
- (NSDictionary *)labelAttributes;

/*!
    Returns attributes of label to be displayed by the receiver in normal mode.
 */
- (NSDictionary *)normalLabelAttributes;

/*!
    Returns attributes of label to be displayed by the receiver in recording mode.
 */
- (NSDictionary *)recordingLabelAttributes;

/*!
    Returns attributes of label to be displayed by the receiver in disabled mode.
 */
- (NSDictionary *)disabledLabelAttributes;


/*!
    Draws background of the receiver into current graphics context.
 */
- (void)drawBackground:(NSRect)aDirtyRect;

/*!
    Draws interior of the receiver into current graphics context.
 */
- (void)drawInterior:(NSRect)aDirtyRect;

/*!
    Draws label of the receiver into current graphics context.
 */
- (void)drawLabel:(NSRect)aDirtyRect;

/*!
    Draws snap back button of the receiver into current graphics context.
 */
- (void)drawSnapBackButton:(NSRect)aDirtyRect;

/*!
    Draws clear button of the receiver into current graphics context.
 */
- (void)drawClearButton:(NSRect)aDirtyRect;


/*!
    Determines whether main button (representation of the receiver in normal mode) is highlighted.
 */
- (BOOL)isMainButtonHighlighted;

/*!
    Determines whether snap back button is highlighted.
 */
- (BOOL)isSnapBackButtonHighlighted;

/*!
    Determines whetehr clear button is highlighted.
 */
- (BOOL)isClearButtonHighlighted;

/*!
    Determines whether modifier flags are valid for key code according to the receiver settings.

    @param      aModifierFlags Proposed modifier flags.

    @param      aKeyCode Code of the pressed key.

    @see    allowedModifierFlags

    @see    allowsEmptyModifierFlags

    @see    requiredModifierFlags
 */
- (BOOL)areModifierFlagsValid:(NSEventModifierFlags)aModifierFlags forKeyCode:(unsigned short)aKeyCode;

/*!
    A helper method to propagate view-driven changes back to model.
 
    @discussion This method makes it easier to propagate changes from a view
                back to the model without overriding bind:toObject:withKeyPath:options:
 
    @see        http://tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/
 */
- (void)propagateValue:(id)aValue forBinding:(NSString *)aBinding;

@end


@protocol SRRecorderControlDelegate <NSObject>

@optional

/*!
    Asks the delegate if editing should begin in the specified shortcut recorder.

    @param      aRecorder The shortcut recorder which editing is about to begin.

    @result     YES if an editing session should be initiated; otherwise, NO to disallow editing.

    @discussion Implementation of this method by the delegate is optional. If it is not present, editing proceeds as if this method had returned YES.
 */
- (BOOL)shortcutRecorderShouldBeginRecording:(SRRecorderControl *)aRecorder;

/*!
    Gives a delegate opportunity to bypass rules specified by allowed and required modifier flags.

    @param      aRecorder The shortcut recorder for which editing ended.

    @param      aModifierFlags Proposed modifier flags.

    @param      aKeyCode Code of the pressed key.

    @result     YES if recorder should bypass key code with given modifier flags despite settings like required modifier flags, allowed modifier flags.

    @discussion Implementation of this method by the delegate is optional.
                Normally, you wouldn't allow a user to record shourcut without modifier flags set: disallow 'a', but allow cmd-'a'.
                However, some keys were designed to be key shortcuts by itself. E.g. Functional keys. By implementing this method a delegate can allow
                these special keys to be set without modifier flags even when the control is configured to disallow empty modifier flags.

    @see    allowedModifierFlags

    @see    allowsEmptyModifierFlags

    @see    requiredModifierFlags
 */
- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder shouldUnconditionallyAllowModifierFlags:(NSEventModifierFlags)aModifierFlags forKeyCode:(unsigned short)aKeyCode;

/*!
    Asks the delegate if the shortcut can be set by the specified shortcut recorder.

    @param      aRecorder The shortcut recorder which shortcut is beign to be recordered.

    @param      aShortcut The Shortcut user typed.

    @result     YES if shortcut can be recordered. Otherwise NO.

    @discussion Implementation of this method by the delegate is optional. If it is not present, shortcut is recordered as if this method had returned YES.
                You may implement this method to filter shortcuts that were already set by other recorders.

    @see        SRValidator
 */
- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder canRecordShortcut:(NSDictionary *)aShortcut;

/*!
    Tells the delegate that editing stopped for the specified shortcut recorder.

    @param      aRecorder The shortcut recorder for which editing ended.

    @discussion Implementation of this method by the delegate is optional.
 */
- (void)shortcutRecorderDidEndRecording:(SRRecorderControl *)aRecorder;

@end


FOUNDATION_STATIC_INLINE BOOL SRShortcutEqualToShortcut(NSDictionary *a, NSDictionary *b)
{
    if (a == b)
        return YES;
    else if (a && !b)
        return NO;
    else if (!a && b)
        return NO;
    else
        return ([a[SRShortcutKeyCode] isEqual:b[SRShortcutKeyCode]] && [a[SRShortcutModifierFlagsKey] isEqual:b[SRShortcutModifierFlagsKey]]);
}


FOUNDATION_STATIC_INLINE NSDictionary *SRShortcutWithCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode)
{
    return @{SRShortcutKeyCode: @(aKeyCode), SRShortcutModifierFlagsKey: @(aModifierFlags)};
}


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRRecorderControl.m
================================================
//
//  SRRecorderControl.m
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Ilya Kulakov

#include <limits.h>

#import "SRRecorderControl.h"
#import "SRKeyCodeTransformer.h"
#import "SRModifierFlagsTransformer.h"


NSString *const SRShortcutKeyCode = @"keyCode";

NSString *const SRShortcutModifierFlagsKey = @"modifierFlags";

NSString *const SRShortcutCharacters = @"characters";

NSString *const SRShortcutCharactersIgnoringModifiers = @"charactersIgnoringModifiers";


// Control Layout Constants

static const CGFloat _SRRecorderControlYosemiteShapeXRadius = 2.0;

static const CGFloat _SRRecorderControlYosemiteShapeYRadius = 2.0;

static const CGFloat _SRRecorderControlShapeXRadius = 11.0;

static const CGFloat _SRRecorderControlShapeYRadius = 12.0;

static const CGFloat _SRRecorderControlHeight = 25.0;

static const CGFloat _SRRecorderControlBottomShadowHeightInPixels = 1.0;

// TODO: see baselineOffsetFromBottom
// static const CGFloat _SRRecorderControlBaselineOffset = 5.0;

// Clear Button Layout Constants

static const CGFloat _SRRecorderControlClearButtonWidth = 14.0;

static const CGFloat _SRRecorderControlClearButtonHeight = 14.0;

static const CGFloat _SRRecorderControlClearButtonRightOffset = 4.0;

static const CGFloat _SRRecorderControlClearButtonLeftOffset = 1.0;

static const NSSize _SRRecorderControlClearButtonSize = {.width = _SRRecorderControlClearButtonWidth, .height = _SRRecorderControlClearButtonHeight};


// SanpBack Button Layout Constants

static const CGFloat _SRRecorderControlSnapBackButtonWidth = 14.0;

static const CGFloat _SRRecorderControlSnapBackButtonHeight = 14.0;

static const CGFloat _SRRecorderControlSnapBackButtonRightOffset = 1.0;

static const CGFloat _SRRecorderControlSnapBackButtonLeftOffset = 3.0;

static const NSSize _SRRecorderControlSnapBackButtonSize = {.width = _SRRecorderControlSnapBackButtonWidth, .height = _SRRecorderControlSnapBackButtonHeight};


static NSImage *_SRImages[19];


typedef NS_ENUM(NSUInteger, _SRRecorderControlButtonTag)
{
    _SRRecorderControlInvalidButtonTag = -1,
    _SRRecorderControlSnapBackButtonTag = 0,
    _SRRecorderControlClearButtonTag = 1,
    _SRRecorderControlMainButtonTag = 2
};


@implementation SRRecorderControl
{
    NSTrackingArea *_mainButtonTrackingArea;
    NSTrackingArea *_snapBackButtonTrackingArea;
    NSTrackingArea *_clearButtonTrackingArea;

    _SRRecorderControlButtonTag _mouseTrackingButtonTag;
    NSToolTipTag _snapBackButtonToolTipTag;

    CGFloat _shapeXRadius;
    CGFloat _shapeYRadious;
}

- (instancetype)initWithFrame:(NSRect)aFrameRect
{
    self = [super initWithFrame:aFrameRect];

    if (self)
    {
        [self _initInternalState];
    }

    return self;
}

- (void)_initInternalState
{
    _allowsEmptyModifierFlags = NO;
    _drawsASCIIEquivalentOfShortcut = YES;
    _allowsEscapeToCancelRecording = YES;
    _allowsDeleteToClearShortcutAndEndRecording = YES;
    _enabled = YES;
    _allowedModifierFlags = SRCocoaModifierFlagsMask;
    _requiredModifierFlags = 0;
    _mouseTrackingButtonTag = _SRRecorderControlInvalidButtonTag;
    _snapBackButtonToolTipTag = NSIntegerMax;

    if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
    {
        self.translatesAutoresizingMaskIntoConstraints = NO;

        [self setContentHuggingPriority:NSLayoutPriorityDefaultLow
                         forOrientation:NSLayoutConstraintOrientationHorizontal];
        [self setContentHuggingPriority:NSLayoutPriorityRequired
                         forOrientation:NSLayoutConstraintOrientationVertical];

        [self setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow
                                       forOrientation:NSLayoutConstraintOrientationHorizontal];
        [self setContentCompressionResistancePriority:NSLayoutPriorityRequired
                                       forOrientation:NSLayoutConstraintOrientationVertical];
    }

    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
    {
        _shapeXRadius = _SRRecorderControlShapeXRadius;
        _shapeYRadious = _SRRecorderControlShapeYRadius;
    }
    else
    {
        _shapeXRadius = _SRRecorderControlYosemiteShapeXRadius;
        _shapeYRadious = _SRRecorderControlYosemiteShapeYRadius;
    }

    [self setToolTip:SRLoc(@"Click to record shortcut")];
    [self updateTrackingAreas];
}


#pragma mark Properties

- (void)setAllowedModifierFlags:(NSEventModifierFlags)newAllowedModifierFlags
          requiredModifierFlags:(NSEventModifierFlags)newRequiredModifierFlags
       allowsEmptyModifierFlags:(BOOL)newAllowsEmptyModifierFlags
{
    newAllowedModifierFlags &= SRCocoaModifierFlagsMask;
    newRequiredModifierFlags &= SRCocoaModifierFlagsMask;

    if ((newAllowedModifierFlags & newRequiredModifierFlags) != newRequiredModifierFlags)
    {
        [NSException raise:NSInvalidArgumentException
                    format:@"Required flags (%lu) MUST be allowed (%lu)", newAllowedModifierFlags, newRequiredModifierFlags];
    }

    if (newAllowsEmptyModifierFlags && newRequiredModifierFlags != 0)
    {
        [NSException raise:NSInvalidArgumentException
                    format:@"Empty modifier flags MUST be disallowed if required modifier flags are not empty."];
    }

    _allowedModifierFlags = newAllowedModifierFlags;
    _requiredModifierFlags = newRequiredModifierFlags;
    _allowsEmptyModifierFlags = newAllowsEmptyModifierFlags;
}

- (void)setEnabled:(BOOL)newEnabled
{
    _enabled = newEnabled;
    [self setNeedsDisplay:YES];

    if (!_enabled)
        [self endRecording];

    // Focus ring is only drawn when view is enabled
    if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
        [self noteFocusRingMaskChanged];
}

- (void)setObjectValue:(NSDictionary *)newObjectValue
{
    // Cocoa KVO and KVC frequently uses NSNull as object substituation of nil.
    // SRRecorderControl expects either nil or valid object value, it's convenient
    // to handle NSNull here and convert it into nil.
    if ((NSNull *)newObjectValue == [NSNull null])
        newObjectValue = nil;

    _objectValue = [newObjectValue copy];
    [self propagateValue:_objectValue forBinding:NSValueBinding];

    if (!self.isRecording)
    {
        NSAccessibilityPostNotification(self, NSAccessibilityTitleChangedNotification);
        [self setNeedsDisplay:YES];
    }
}


#pragma mark Methods

- (BOOL)beginRecording
{
    if (!self.enabled)
        return NO;

    if (self.isRecording)
        return YES;

    [self setNeedsDisplay:YES];

    if ([self.delegate respondsToSelector:@selector(shortcutRecorderShouldBeginRecording:)])
    {
        if (![self.delegate shortcutRecorderShouldBeginRecording:self])
        {
            NSBeep();
            return NO;
        }
    }

    [self willChangeValueForKey:@"isRecording"];
    _isRecording = YES;
    [self didChangeValueForKey:@"isRecording"];

    [self updateTrackingAreas];
    [self setToolTip:SRLoc(@"Type shortcut")];
    NSAccessibilityPostNotification(self, NSAccessibilityTitleChangedNotification);
    return YES;
}

- (void)endRecording
{
    [self endRecordingWithObjectValue:self.objectValue];
}

- (void)clearAndEndRecording
{
    [self endRecordingWithObjectValue:nil];
}

- (void)endRecordingWithObjectValue:(NSDictionary *)anObjectValue
{
    if (!self.isRecording)
        return;

    [self willChangeValueForKey:@"isRecording"];
    _isRecording = NO;
    [self didChangeValueForKey:@"isRecording"];

    self.objectValue = anObjectValue;

    [self updateTrackingAreas];
    [self setToolTip:SRLoc(@"Click to record shortcut")];
    [self setNeedsDisplay:YES];
    NSAccessibilityPostNotification(self, NSAccessibilityTitleChangedNotification);

    if (self.window.firstResponder == self && ![self canBecomeKeyView])
        [self.window makeFirstResponder:nil];

    if ([self.delegate respondsToSelector:@selector(shortcutRecorderDidEndRecording:)])
        [self.delegate shortcutRecorderDidEndRecording:self];
}


#pragma mark -

- (NSBezierPath *)controlShape
{
    NSRect shapeBounds = self.bounds;
    shapeBounds.size.height = _SRRecorderControlHeight - self.alignmentRectInsets.bottom;

    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
    {
        shapeBounds = NSInsetRect(shapeBounds, 1.0, 1.0);
    }

    return [NSBezierPath bezierPathWithRoundedRect:shapeBounds
                                           xRadius:_shapeXRadius
                                           yRadius:_shapeYRadious];
}

- (NSRect)rectForLabel:(NSString *)aLabel withAttributes:(NSDictionary *)anAttributes
{
    NSSize labelSize = [aLabel sizeWithAttributes:anAttributes];
    NSRect enclosingRect = NSInsetRect(self.bounds, _shapeXRadius, 0.0);
    labelSize.width = fmin(ceil(labelSize.width), NSWidth(enclosingRect));
    labelSize.height = ceil(labelSize.height);
    CGFloat fontBaselineOffsetFromTop = labelSize.height + [anAttributes[NSFontAttributeName] descender];
    CGFloat baselineOffsetFromTop = _SRRecorderControlHeight - self.baselineOffsetFromBottom;
    NSRect labelRect = {
        .origin = NSMakePoint(NSMidX(enclosingRect) - labelSize.width / 2.0, baselineOffsetFromTop - fontBaselineOffsetFromTop),
        .size = labelSize
    };
    labelRect = [self centerScanRect:labelRect];

    // Ensure label and buttons do not overlap.
    if (self.isRecording)
    {
        CGFloat rightOffsetFromButtons = NSMinX(self.snapBackButtonRect) - NSMaxX(labelRect);

        if (rightOffsetFromButtons < 0.0)
        {
            labelRect = NSOffsetRect(labelRect, rightOffsetFromButtons, 0.0);

            if (NSMinX(labelRect) < NSMinX(enclosingRect))
            {
                labelRect.size.width -= NSMinX(enclosingRect) - NSMinX(labelRect);
                labelRect.origin.x = NSMinX(enclosingRect);
            }
        }
    }

#ifdef DEBUG
    if (labelRect.size.width < labelSize.width || labelRect.size.height < labelSize.height)
        NSLog(@"WARNING: label rect (%@) is smaller than label size (%@). You may want to adjust size of the control.", NSStringFromRect(labelRect), NSStringFromSize(labelSize));
#endif

    return labelRect;
}

- (NSRect)snapBackButtonRect
{
    NSRect clearButtonRect = self.clearButtonRect;
    NSRect bounds = self.bounds;
    NSRect snapBackButtonRect = NSZeroRect;
    snapBackButtonRect.origin.x = NSMinX(clearButtonRect) - _SRRecorderControlSnapBackButtonRightOffset - _SRRecorderControlSnapBackButtonSize.width - _SRRecorderControlSnapBackButtonLeftOffset;
    snapBackButtonRect.origin.y = NSMinY(bounds);
    snapBackButtonRect.size.width = fdim(NSMinX(clearButtonRect), NSMinX(snapBackButtonRect));
    snapBackButtonRect.size.height = _SRRecorderControlHeight;
    return snapBackButtonRect;
}

- (NSRect)clearButtonRect
{
    NSRect bounds = self.bounds;

    if ([self.objectValue count])
    {
        NSRect clearButtonRect = NSZeroRect;
        clearButtonRect.origin.x = NSMaxX(bounds) - _SRRecorderControlClearButtonRightOffset - _SRRecorderControlClearButtonSize.width - _SRRecorderControlClearButtonLeftOffset;
        clearButtonRect.origin.y = NSMinY(bounds);
        clearButtonRect.size.width = fdim(NSMaxX(bounds), NSMinX(clearButtonRect));
        clearButtonRect.size.height = _SRRecorderControlHeight;
        return clearButtonRect;
    }
    else
    {
        return NSMakeRect(NSMaxX(bounds) - _SRRecorderControlClearButtonRightOffset - _SRRecorderControlClearButtonLeftOffset,
                          NSMinY(bounds),
                          0.0,
                          _SRRecorderControlHeight);
    }
}


#pragma mark -

- (NSString *)label
{
    NSString *label = nil;

    if (self.isRecording)
    {
        NSEventModifierFlags modifierFlags = [NSEvent modifierFlags] & self.allowedModifierFlags;

        if (modifierFlags)
            label = [[SRModifierFlagsTransformer sharedTransformer] transformedValue:@(modifierFlags)];
        else
            label = self.stringValue;

        if (![label length])
            label = SRLoc(@"Type shortcut");
    }
    else
    {
        label = self.stringValue;

        if (![label length])
            label = SRLoc(@"Click to record shortcut");
    }

    return label;
}

- (NSString *)accessibilityLabel
{
    NSString *label = nil;

    if (self.isRecording)
    {
        NSEventModifierFlags modifierFlags = [NSEvent modifierFlags] & self.allowedModifierFlags;
        label = [[SRModifierFlagsTransformer sharedPlainTransformer] transformedValue:@(modifierFlags)];

        if (![label length])
            label = SRLoc(@"Type shortcut");
    }
    else
    {
        label = self.accessibilityStringValue;

        if (![label length])
            label = SRLoc(@"Click to record shortcut");
    }

    return label;
}

- (NSString *)stringValue
{
    if (![self.objectValue count])
        return nil;

    NSString *f = [[SRModifierFlagsTransformer sharedTransformer] transformedValue:self.objectValue[SRShortcutModifierFlagsKey]];
    SRKeyCodeTransformer *transformer = nil;

    if (self.drawsASCIIEquivalentOfShortcut)
        transformer = [SRKeyCodeTransformer sharedPlainASCIITransformer];
    else
        transformer = [SRKeyCodeTransformer sharedPlainTransformer];

    NSString *c = [transformer transformedValue:self.objectValue[SRShortcutKeyCode]
                      withImplicitModifierFlags:nil
                          explicitModifierFlags:self.objectValue[SRShortcutModifierFlagsKey]];

    return [NSString stringWithFormat:@"%@%@", f, c];
}

- (NSString *)accessibilityStringValue
{
    if (![self.objectValue count])
        return nil;

    NSString *f = [[SRModifierFlagsTransformer sharedPlainTransformer] transformedValue:self.objectValue[SRShortcutModifierFlagsKey]];
    NSString *c = nil;

    if (self.drawsASCIIEquivalentOfShortcut)
        c = [[SRKeyCodeTransformer sharedPlainASCIITransformer] transformedValue:self.objectValue[SRShortcutKeyCode]];
    else
        c = [[SRKeyCodeTransformer sharedPlainTransformer] transformedValue:self.objectValue[SRShortcutKeyCode]];

    if ([f length] > 0)
        return [NSString stringWithFormat:@"%@-%@", f, c];
    else
        return [NSString stringWithFormat:@"%@", c];
}

- (NSDictionary *)labelAttributes
{
    if (self.enabled)
    {
        if (self.isRecording)
            return [self recordingLabelAttributes];
        else
            return [self normalLabelAttributes];
    }
    else
        return [self disabledLabelAttributes];
}

- (NSDictionary *)normalLabelAttributes
{
    static dispatch_once_t OnceToken;
    static NSDictionary *NormalAttributes = nil;
    dispatch_once(&OnceToken, ^{
        NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];
        p.alignment = NSTextAlignmentCenter;
        p.lineBreakMode = NSLineBreakByTruncatingTail;
        p.baseWritingDirection = NSWritingDirectionLeftToRight;
        NormalAttributes = @{
            NSParagraphStyleAttributeName: [p copy],
            NSFontAttributeName: [NSFont fontWithName:@"Avenir" size:[NSFont systemFontSize]],
            NSForegroundColorAttributeName: [NSColor controlTextColor]
        };
    });
    return NormalAttributes;
}

- (NSDictionary *)recordingLabelAttributes
{
    static dispatch_once_t OnceToken;
    static NSDictionary *RecordingAttributes = nil;
    dispatch_once(&OnceToken, ^{
        NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];
        p.alignment = NSTextAlignmentCenter;
        p.lineBreakMode = NSLineBreakByTruncatingTail;
        p.baseWritingDirection = NSWritingDirectionLeftToRight;
        RecordingAttributes = @{
            NSParagraphStyleAttributeName: [p copy],
            NSFontAttributeName: [NSFont fontWithName:@"Avenir" size:[NSFont systemFontSize]],
            NSForegroundColorAttributeName: [NSColor disabledControlTextColor]
        };
    });
    return RecordingAttributes;
}

- (NSDictionary *)disabledLabelAttributes
{
    static dispatch_once_t OnceToken;
    static NSDictionary *DisabledAttributes = nil;
    dispatch_once(&OnceToken, ^{
        NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];
        p.alignment = NSTextAlignmentCenter;
        p.lineBreakMode = NSLineBreakByTruncatingTail;
        p.baseWritingDirection = NSWritingDirectionLeftToRight;
        DisabledAttributes = @{
            NSParagraphStyleAttributeName: [p copy],
            NSFontAttributeName: [NSFont labelFontOfSize:[NSFont systemFontSize]],
            NSForegroundColorAttributeName: [NSColor disabledControlTextColor]
        };
    });
    return DisabledAttributes;
}


#pragma mark -

- (void)drawBackground:(NSRect)aDirtyRect
{
    NSRect frame = self.bounds;
    frame.size.height = _SRRecorderControlHeight;

    if (![self needsToDrawRect:frame])
        return;

    [NSGraphicsContext saveGraphicsState];

    if (self.isRecording)
    {
        NSDrawThreePartImage(frame,
                             _SRImages[3],
                             _SRImages[4],
                             _SRImages[5],
                             NO,
                             NSCompositingOperationSourceOver,
                             1.0,
                             self.isFlipped);
    }
    else
    {
        if (self.isMainButtonHighlighted)
        {
            if ([NSColor currentControlTint] == NSBlueControlTint)
            {
                NSDrawThreePartImage(frame,
                                     _SRImages[0],
                                     _SRImages[1],
                                     _SRImages[2],
                                     NO,
                                     NSCompositingOperationSourceOver,
                                     1.0,
                                     self.isFlipped);
            }
            else
            {
                NSDrawThreePartImage(frame,
                                     _SRImages[6],
                                     _SRImages[7],
                                     _SRImages[8],
                                     NO,
                                     NSCompositingOperationSourceOver,
                                     1.0,
                                     self.isFlipped);
            }
        }
        else if (self.enabled)
        {
            NSDrawThreePartImage(frame,
                                 _SRImages[9],
                                 _SRImages[10],
                                 _SRImages[11],
                                 NO,
                                 NSCompositingOperationSourceOver,
                                 1.0,
                                 self.isFlipped);
        }
        else
        {
            NSDrawThreePartImage(frame,
                                 _SRImages[16],
                                 _SRImages[17],
                                 _SRImages[18],
                                 NO,
                                 NSCompositingOperationSourceOver,
                                 1.0,
                                 self.isFlipped);
        }
    }

    [NSGraphicsContext restoreGraphicsState];
}

- (void)drawInterior:(NSRect)aDirtyRect
{
    [self drawLabel:aDirtyRect];

    if (self.isRecording)
    {
        [self drawSnapBackButton:aDirtyRect];
        [self drawClearButton:aDirtyRect];
    }
}

- (void)drawLabel:(NSRect)aDirtyRect
{
    NSString *label = self.label;
    NSDictionary *labelAttributes = self.labelAttributes;
    NSRect labelRect = [self rectForLabel:label withAttributes:labelAttributes];

    if (![self needsToDrawRect:labelRect])
        return;

    [NSGraphicsContext saveGraphicsState];
    [label drawInRect:labelRect withAttributes:labelAttributes];
    [NSGraphicsContext restoreGraphicsState];
}

- (void)drawSnapBackButton:(NSRect)aDirtyRect
{
    NSRect imageRect = self.snapBackButtonRect;
    imageRect.origin.x += _SRRecorderControlSnapBackButtonLeftOffset;
    imageRect.origin.y += floor(self.alignmentRectInsets.top + (NSHeight(imageRect) - _SRRecorderControlSnapBackButtonSize.height) / 2.0);
    imageRect.size = _SRRecorderControlSnapBackButtonSize;
    imageRect = [self centerScanRect:imageRect];

    if (![self needsToDrawRect:imageRect])
        return;

    [NSGraphicsContext saveGraphicsState];

    if (self.isSnapBackButtonHighlighted)
    {
        [_SRImages[14] drawInRect:imageRect
                         fromRect:NSZeroRect
                        operation:NSCompositingOperationSourceOver
                         fraction:1.0];
    }
    else
    {
        [_SRImages[15] drawInRect:imageRect
                         fromRect:NSZeroRect
                        operation:NSCompositingOperationSourceOver
                         fraction:1.0];
    }

    [NSGraphicsContext restoreGraphicsState];
}

- (void)drawClearButton:(NSRect)aDirtyRect
{
    NSRect imageRect = self.clearButtonRect;

    // If there is no reason to draw clear button (e.g. no shortcut was set)
    // rect will have empty width.
    if (NSWidth(imageRect) == 0.0)
        return;

    imageRect.origin.x += _SRRecorderControlClearButtonLeftOffset;
    imageRect.origin.y += floor(self.alignmentRectInsets.top + (NSHeight(imageRect) - _SRRecorderControlClearButtonSize.height) / 2.0);
    imageRect.size = _SRRecorderControlClearButtonSize;
    imageRect = [self centerScanRect:imageRect];

    if (![self needsToDrawRect:imageRect])
        return;

    [NSGraphicsContext saveGraphicsState];

    if (self.isClearButtonHighlighted)
    {
        [_SRImages[12] drawInRect:imageRect
                         fromRect:NSZeroRect
                        operation:NSCompositingOperationSourceOver
                         fraction:1.0];
    }
    else
    {
        [_SRImages[13] drawInRect:imageRect
                         fromRect:NSZeroRect
                        operation:NSCompositingOperationSourceOver
                         fraction:1.0];
    }

    [NSGraphicsContext restoreGraphicsState];
}

- (CGFloat)backingScaleFactor
{
    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6 || self.window == nil)
        return 1.0;
    else
        return self.window.backingScaleFactor;
}


#pragma mark -

- (BOOL)isMainButtonHighlighted
{
    if (_mouseTrackingButtonTag == _SRRecorderControlMainButtonTag)
    {
        NSPoint locationInView = [self convertPoint:self.window.mouseLocationOutsideOfEventStream
                                           fromView:nil];
        return [self mouse:locationInView inRect:self.bounds];
    }
    else
        return NO;
}

- (BOOL)isSnapBackButtonHighlighted
{
    if (_mouseTrackingButtonTag == _SRRecorderControlSnapBackButtonTag)
    {
        NSPoint locationInView = [self convertPoint:self.window.mouseLocationOutsideOfEventStream
                                           fromView:nil];
        return [self mouse:locationInView inRect:self.snapBackButtonRect];
    }
    else
        return NO;
}

- (BOOL)isClearButtonHighlighted
{
    if (_mouseTrackingButtonTag == _SRRecorderControlClearButtonTag)
    {
        NSPoint locationInView = [self convertPoint:self.window.mouseLocationOutsideOfEventStream
                                           fromView:nil];
        return [self mouse:locationInView inRect:self.clearButtonRect];
    }
    else
        return NO;
}

- (BOOL)areModifierFlagsValid:(NSEventModifierFlags)aModifierFlags forKeyCode:(unsigned short)aKeyCode
{
    aModifierFlags &= SRCocoaModifierFlagsMask;

    if ([self.delegate respondsToSelector:@selector(shortcutRecorder:shouldUnconditionallyAllowModifierFlags:forKeyCode:)] &&
        [self.delegate shortcutRecorder:self shouldUnconditionallyAllowModifierFlags:aModifierFlags forKeyCode:aKeyCode])
    {
        return YES;
    }
    else if (aModifierFlags == 0 && !self.allowsEmptyModifierFlags)
        return NO;
    else if ((aModifierFlags & self.requiredModifierFlags) != self.requiredModifierFlags)
        return NO;
    else if ((aModifierFlags & self.allowedModifierFlags) != aModifierFlags)
        return NO;
    else
        return YES;
}


#pragma mark -

- (void)propagateValue:(id)aValue forBinding:(NSString *)aBinding
{
    NSParameterAssert(aBinding != nil);

    NSDictionary* bindingInfo = [self infoForBinding:aBinding];

    if(!bindingInfo || (id)bindingInfo == [NSNull null])
        return;

    NSObject *boundObject = bindingInfo[NSObservedObjectKey];

    if(!boundObject || (id)boundObject == [NSNull null])
        [NSException raise:NSInternalInconsistencyException format:@"NSObservedObjectKey MUST NOT be nil for binding \"%@\"", aBinding];

    NSString* boundKeyPath = bindingInfo[NSObservedKeyPathKey];

    if(!boundKeyPath || (id)boundKeyPath == [NSNull null])
        [NSException raise:NSInternalInconsistencyException format:@"NSObservedKeyPathKey MUST NOT be nil for binding \"%@\"", aBinding];

    NSDictionary* bindingOptions = bindingInfo[NSOptionsKey];

    if(bindingOptions)
    {
        NSValueTransformer* transformer = [bindingOptions valueForKey:NSValueTransformerBindingOption];

        if(!transformer || (id)transformer == [NSNull null])
        {
            NSString* transformerName = [bindingOptions valueForKey:NSValueTransformerNameBindingOption];

            if(transformerName && (id)transformerName != [NSNull null])
                transformer = [NSValueTransformer valueTransformerForName:transformerName];
        }

        if(transformer && (id)transformer != [NSNull null])
        {
            if([[transformer class] allowsReverseTransformation])
                aValue = [transformer reverseTransformedValue:aValue];
#ifdef DEBUG
            else
                NSLog(@"WARNING: binding \"%@\" has value transformer, but it doesn't allow reverse transformations in %s", aBinding, __PRETTY_FUNCTION__);
#endif
        }
    }

    [boundObject setValue:aValue forKeyPath:boundKeyPath];
}

+ (BOOL)automaticallyNotifiesObserversOfValue
{
    return NO;
}

- (void)setValue:(id)newValue
{
    if (NSIsControllerMarker(newValue))
        [NSException raise:NSInternalInconsistencyException format:@"SRRecorderControl's NSValueBinding does not support controller value markers."];

    self.objectValue = newValue;
}

- (id)value
{
    return self.objectValue;
}

#pragma mark NSToolTipOwner

- (NSString *)view:(NSView *)aView stringForToolTip:(NSToolTipTag)aTag point:(NSPoint)aPoint userData:(void *)aData
{
    if (aTag == _snapBackButtonToolTipTag)
        return SRLoc(@"Use old shortcut");
    else
        return [super view:aView stringForToolTip:aTag point:aPoint userData:aData];
}


#pragma mark NSCoding

- (instancetype)initWithCoder:(NSCoder *)aCoder
{
    // Since Xcode 6.x, user can configure xib to Prefer Coder.
    // In that case view will be instantiated with initWithCoder.
    //
    // awakeFromNib cannot be used to set up defaults for IBDesignable,
    // because at the time it's called, it's impossible to know whether properties
    // were set by a user in xib or they are compilation-time defaults.
    self = [super initWithCoder:aCoder];

    if (self)
    {
        [self _initInternalState];
    }

    return self;
}


#pragma mark NSView

- (BOOL)isOpaque
{
    return NO;
}

- (BOOL)isFlipped
{
    return YES;
}

- (void)viewWillDraw
{
    [super viewWillDraw];

    static dispatch_once_t OnceToken;
    dispatch_once(&OnceToken, ^{
        if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
        {
            _SRImages[0] = SRImage(@"shortcut-recorder-bezel-blue-highlighted-left");
            _SRImages[1] = SRImage(@"shortcut-recorder-bezel-blue-highlighted-middle");
            _SRImages[2] = SRImage(@"shortcut-recorder-bezel-blue-highlighted-right");
            _SRImages[3] = SRImage(@"shortcut-recorder-bezel-editing-left");
            _SRImages[4] = SRImage(@"shortcut-recorder-bezel-editing-middle");
            _SRImages[5] = SRImage(@"shortcut-recorder-bezel-editing-right");
            _SRImages[6] = SRImage(@"shortcut-recorder-bezel-graphite-highlight-mask-left");
            _SRImages[7] = SRImage(@"shortcut-recorder-bezel-graphite-highlight-mask-middle");
            _SRImages[8] = SRImage(@"shortcut-recorder-bezel-graphite-highlight-mask-right");
            _SRImages[9] = SRImage(@"shortcut-recorder-bezel-left");
            _SRImages[10] = SRImage(@"shortcut-recorder-bezel-middle");
            _SRImages[11] = SRImage(@"shortcut-recorder-bezel-right");
            _SRImages[12] = SRImage(@"shortcut-recorder-clear-highlighted");
            _SRImages[13] = SRImage(@"shortcut-recorder-clear");
            _SRImages[14] = SRImage(@"shortcut-recorder-snapback-highlighted");
            _SRImages[15] = SRImage(@"shortcut-recorder-snapback");
            _SRImages[16] = SRImage(@"shortcut-recorder-bezel-disabled-left");
            _SRImages[17] = SRImage(@"shortcut-recorder-bezel-disabled-middle");
            _SRImages[18] = SRImage(@"shortcut-recorder-bezel-disabled-right");
        }
        else
        {
            _SRImages[0] = SRImage(@"shortcut-recorder-yosemite-bezel-blue-highlighted-left");
            _SRImages[1] = SRImage(@"shortcut-recorder-yosemite-bezel-blue-highlighted-middle");
            _SRImages[2] = SRImage(@"shortcut-recorder-yosemite-bezel-blue-highlighted-right");
            _SRImages[3] = SRImage(@"shortcut-recorder-yosemite-bezel-editing-left");
            _SRImages[4] = SRImage(@"shortcut-recorder-yosemite-bezel-editing-middle");
            _SRImages[5] = SRImage(@"shortcut-recorder-yosemite-bezel-editing-right");
            _SRImages[6] = SRImage(@"shortcut-recorder-yosemite-bezel-graphite-highlight-mask-left");
            _SRImages[7] = SRImage(@"shortcut-recorder-yosemite-bezel-graphite-highlight-mask-middle");
            _SRImages[8] = SRImage(@"shortcut-recorder-yosemite-bezel-graphite-highlight-mask-right");
            _SRImages[9] = SRImage(@"shortcut-recorder-yosemite-bezel-left");
            _SRImages[10] = SRImage(@"shortcut-recorder-yosemite-bezel-middle");
            _SRImages[11] = SRImage(@"shortcut-recorder-yosemite-bezel-right");
            _SRImages[12] = SRImage(@"shortcut-recorder-yosemite-clear-highlighted");
            _SRImages[13] = SRImage(@"shortcut-recorder-yosemite-clear");
            _SRImages[14] = SRImage(@"shortcut-recorder-yosemite-snapback-highlighted");
            _SRImages[15] = SRImage(@"shortcut-recorder-yosemite-snapback");
            _SRImages[16] = SRImage(@"shortcut-recorder-yosemite-bezel-disabled-left");
            _SRImages[17] = SRImage(@"shortcut-recorder-yosemite-bezel-disabled-middle");
            _SRImages[18] = SRImage(@"shortcut-recorder-yosemite-bezel-disabled-right");
        }
    });
}

- (void)drawRect:(NSRect)aDirtyRect
{
    [self drawBackground:aDirtyRect];
    [self drawInterior:aDirtyRect];

    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6)
    {
        if (self.enabled && self.window.firstResponder == self)
        {
            [NSGraphicsContext saveGraphicsState];
            NSSetFocusRingStyle(NSFocusRingOnly);
            [self.controlShape fill];
            [NSGraphicsContext restoreGraphicsState];
        }
    }
}

- (void)drawFocusRingMask
{
    if (self.enabled && self.window.firstResponder == self)
        [self.controlShape fill];
}

- (NSRect)focusRingMaskBounds
{
    if (self.enabled && self.window.firstResponder == self)
        return self.controlShape.bounds;
    else
        return NSZeroRect;
}

- (NSEdgeInsets)alignmentRectInsets
{
    return NSEdgeInsetsMake(0.0, 0.0, _SRRecorderControlBottomShadowHeightInPixels / self.backingScaleFactor, 0.0);
}

- (CGFloat)baselineOffsetFromBottom
{
    // True method to calculate is presented below. Unfortunately Cocoa implementation of Mac OS X 10.8.2 expects this value to be persistant.
    // If baselineOffsetFromBottom depends on some other properties and may return different values for different calls,
    // NSLayoutFormatAlignAllBaseline may not work. For this reason we return the constant.
    // If you're going to change layout of the view, uncomment the line below, look what it typically returns and update the constant.
    // TODO: Hopefully it will be fixed some day in Cocoa and therefore in SRRecorderControl.
//    CGFloat baseline = fdim(NSHeight(self.bounds), _SRRecorderControlHeight) + floor(_SRRecorderControlBaselineOffset - [self.labelAttributes[NSFontAttributeName] descender]);
    return 8.0;
}

- (NSSize)intrinsicContentSize
{
    return NSMakeSize(NSWidth([self rectForLabel:SRLoc(@"Click to record shortcut") withAttributes:self.normalLabelAttributes]) + _shapeXRadius + _shapeXRadius,
                      _SRRecorderControlHeight);
}

- (void)updateTrackingAreas
{
    static const NSTrackingAreaOptions TrackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveWhenFirstResponder | NSTrackingEnabledDuringMouseDrag;

    if (_mainButtonTrackingArea)
        [self removeTrackingArea:_mainButtonTrackingArea];

    _mainButtonTrackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds
                                                        options:TrackingOptions
                                                          owner:self
                                                       userInfo:nil];
    [self addTrackingArea:_mainButtonTrackingArea];

    if (_snapBackButtonTrackingArea)
    {
        [self removeTrackingArea:_snapBackButtonTrackingArea];
        _snapBackButtonTrackingArea = nil;
    }

    if (_clearButtonTrackingArea)
    {
        [self removeTrackingArea:_clearButtonTrackingArea];
        _clearButtonTrackingArea = nil;
    }

    if (_snapBackButtonToolTipTag != NSIntegerMax)
    {
        [self removeToolTip:_snapBackButtonToolTipTag];
        _snapBackButtonToolTipTag = NSIntegerMax;
    }

    if (self.isRecording)
    {
        _snapBackButtonTrackingArea = [[NSTrackingArea alloc] initWithRect:self.snapBackButtonRect
                                                                   options:TrackingOptions
                                                                     owner:self
                                                                  userInfo:nil];
        [self addTrackingArea:_snapBackButtonTrackingArea];
        _clearButtonTrackingArea = [[NSTrackingArea alloc] initWithRect:self.clearButtonRect
                                                                options:TrackingOptions
                                                                  owner:self
                                                               userInfo:nil];
        [self addTrackingArea:_clearButtonTrackingArea];

        // Since this method is used to set up tracking rects of aux buttons, the rest of the code is aware
        // it should be called whenever geometry or apperance changes. Therefore it's a good place to set up tooltip rects.
        _snapBackButtonToolTipTag = [self addToolTipRect:[_snapBackButtonTrackingArea rect] owner:self userData:NULL];
    }
}

- (void)viewWillMoveToWindow:(NSWindow *)aWindow
{
    // We want control to end recording whenever window resigns first responder status.
    // Otherwise we could end up with "dangling" recording.
    if (self.window)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:NSWindowDidResignKeyNotification
                                                      object:self.window];
    }

    if (aWindow)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(endRecording)
                                                     name:NSWindowDidResignKeyNotification
                                                   object:aWindow];
    }

    [super viewWillMoveToWindow:aWindow];
}


#pragma mark NSResponder

- (BOOL)acceptsFirstResponder
{
    return self.enabled;
}

- (BOOL)becomeFirstResponder
{
    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6)
        [self setKeyboardFocusRingNeedsDisplayInRect:self.bounds];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6)
        [self setKeyboardFocusRingNeedsDisplayInRect:self.bounds];

    [self endRecording];
    _mouseTrackingButtonTag = _SRRecorderControlInvalidButtonTag;
    return [super resignFirstResponder];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)anEvent
{
    return YES;
}

- (BOOL)canBecomeKeyView
{
    // SRRecorderControl uses the button metaphor, but buttons cannot become key unless
    // Full Keyboard Access is enabled. Respect this.
    return [super canBecomeKeyView] && [NSApp isFullKeyboardAccessEnabled];
}

- (BOOL)needsPanelToBecomeKey
{
    return YES;
}

- (void)mouseDown:(NSEvent *)anEvent
{
    if (!self.enabled)
    {
        [super mouseDown:anEvent];
        return;
    }

    NSPoint locationInView = [self convertPoint:anEvent.locationInWindow fromView:nil];

    if (self.isRecording)
    {
        if ([self mouse:locationInView inRect:self.snapBackButtonRect])
        {
            _mouseTrackingButtonTag = _SRRecorderControlSnapBackButtonTag;
            [self setNeedsDisplayInRect:self.snapBackButtonRect];
        }
        else if ([self mouse:locationInView inRect:self.clearButtonRect])
        {
            _mouseTrackingButtonTag = _SRRecorderControlClearButtonTag;
            [self setNeedsDisplayInRect:self.clearButtonRect];
        }
        else
            [super mouseDown:anEvent];
    }
    else if ([self mouse:locationInView inRect:self.bounds])
    {
        _mouseTrackingButtonTag = _SRRecorderControlMainButtonTag;
        [self setNeedsDisplay:YES];
    }
    else
        [super mouseDown:anEvent];
}

- (void)mouseUp:(NSEvent *)anEvent
{
    if (!self.enabled)
    {
        [super mouseUp:anEvent];
        return;
    }

    if (_mouseTrackingButtonTag != _SRRecorderControlInvalidButtonTag)
    {
        if (!self.window.isKeyWindow)
        {
            // It's possible to receive this event after window resigned its key status
            // e.g. when shortcut brings new window and makes it key.
            [self setNeedsDisplay:YES];
        }
        else
        {
            NSPoint locationInView = [self convertPoint:anEvent.locationInWindow fromView:nil];

            if (_mouseTrackingButtonTag == _SRRecorderControlMainButtonTag &&
                [self mouse:locationInView inRect:self.bounds])
            {
                [self beginRecording];
            }
            else if (_mouseTrackingButtonTag == _SRRecorderControlSnapBackButtonTag &&
                     [self mouse:locationInView inRect:self.snapBackButtonRect])
            {
                [self endRecording];
            }
            else if (_mouseTrackingButtonTag == _SRRecorderControlClearButtonTag &&
                     [self mouse:locationInView inRect:self.clearButtonRect])
            {
                [self clearAndEndRecording];
            }
        }

        _mouseTrackingButtonTag = _SRRecorderControlInvalidButtonTag;
    }
    else
        [super mouseUp:anEvent];
}

- (void)mouseEntered:(NSEvent *)anEvent
{
    if (!self.enabled)
    {
        [super mouseEntered:anEvent];
        return;
    }

    if ((_mouseTrackingButtonTag == _SRRecorderControlMainButtonTag && anEvent.trackingArea == _mainButtonTrackingArea) ||
        (_mouseTrackingButtonTag == _SRRecorderControlSnapBackButtonTag && anEvent.trackingArea == _snapBackButtonTrackingArea) ||
        (_mouseTrackingButtonTag == _SRRecorderControlClearButtonTag && anEvent.trackingArea == _clearButtonTrackingArea))
    {
        [self setNeedsDisplayInRect:anEvent.trackingArea.rect];
    }

    [super mouseEntered:anEvent];
}

- (void)mouseExited:(NSEvent *)anEvent
{
    if (!self.enabled)
    {
        [super mouseExited:anEvent];
        return;
    }

    if ((_mouseTrackingButtonTag == _SRRecorderControlMainButtonTag && anEvent.trackingArea == _mainButtonTrackingArea) ||
        (_mouseTrackingButtonTag == _SRRecorderControlSnapBackButtonTag && anEvent.trackingArea == _snapBackButtonTrackingArea) ||
        (_mouseTrackingButtonTag == _SRRecorderControlClearButtonTag && anEvent.trackingArea == _clearButtonTrackingArea))
    {
        [self setNeedsDisplayInRect:anEvent.trackingArea.rect];
    }

    [super mouseExited:anEvent];
}

- (void)keyDown:(NSEvent *)anEvent
{
    if (![self performKeyEquivalent:anEvent])
        [super keyDown:anEvent];
}

- (BOOL)performKeyEquivalent:(NSEvent *)anEvent
{
    if (!self.enabled)
        return NO;

    if (self.window.firstResponder != self)
        return NO;

    if (_mouseTrackingButtonTag != _SRRecorderControlInvalidButtonTag)
        return NO;

    if (self.isRecording)
    {
        if (anEvent.keyCode == USHRT_MAX)
        {
            // This shouldn't really happen ever, but was rarely observed.
            // See https://github.com/Kentzo/ShortcutRecorder/issues/40
            return NO;
        }
        else if (self.allowsEscapeToCancelRecording &&
            anEvent.keyCode == kVK_Escape &&
            (anEvent.modifierFlags & SRCocoaModifierFlagsMask) == 0)
        {
            [self endRecording];
            return YES;
        }
        else if (self.allowsDeleteToClearShortcutAndEndRecording &&
                (anEvent.keyCode == kVK_Delete || anEvent.keyCode == kVK_ForwardDelete) &&
                (anEvent.modifierFlags & SRCocoaModifierFlagsMask) == 0)
        {
            [self clearAndEndRecording];
            return YES;
        }
        else if ([self areModifierFlagsValid:anEvent.modifierFlags forKeyCode:anEvent.keyCode])
        {
            NSDictionary *newObjectValue = @{
                SRShortcutKeyCode: @(anEvent.keyCode),
                SRShortcutModifierFlagsKey: @(anEvent.modifierFlags & SRCocoaModifierFlagsMask),
                SRShortcutCharacters: anEvent.characters,
                SRShortcutCharactersIgnoringModifiers: anEvent.charactersIgnoringModifiers
            };

            if ([self.delegate respondsToSelector:@selector(shortcutRecorder:canRecordShortcut:)])
            {
                if (![self.delegate shortcutRecorder:self canRecordShortcut:newObjectValue])
                {
                    // We acutally handled key equivalent, because client likely performs some action
                    // to represent an error (e.g. beep and error dialog).
                    // Do not end editing, because if client do not use additional window to show an error
                    // first responder will not change. Allow a user to make another attempt.
                    return YES;
                }
            }

            [self endRecordingWithObjectValue:newObjectValue];
            return YES;
        }
    }
    else if (anEvent.keyCode == kVK_Space)
        return [self beginRecording];

    return NO;
}

- (void)flagsChanged:(NSEvent *)anEvent
{
    if (self.isRecording)
    {
        NSEventModifierFlags modifierFlags = anEvent.modifierFlags & SRCocoaModifierFlagsMask;
        if (modifierFlags != 0 && ![self areModifierFlagsValid:modifierFlags forKeyCode:anEvent.keyCode])
            NSBeep();

        [self setNeedsDisplay:YES];
    }

    [super flagsChanged:anEvent];
}


#pragma mark NSObject

+ (void)initialize
{
    if (self == [SRRecorderControl class])
    {
        [self exposeBinding:NSValueBinding];
        [self exposeBinding:NSEnabledBinding];
    }
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRValidator.h
================================================
//
//  SRValidator.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Andy Kim
//      Silvio Rizzi
//      Ilya Kulakov

#import <Cocoa/Cocoa.h>


@protocol SRValidatorDelegate;

/*!
    Implements logic to check whether shortcut is taken by other parts of the application and system.
 */
@interface SRValidator : NSObject

@property (assign) NSObject<SRValidatorDelegate> *delegate;

- (instancetype)initWithDelegate:(NSObject<SRValidatorDelegate> *)aDelegate;

/*!
    Determines whether shortcut is taken.

    @discussion Key is checked in the following order:
                1. If delegate implements shortcutValidator:isKeyCode:andFlagsTaken:reason:
                2. If delegate allows system-wide shortcuts are checked
                3. If delegate allows application menu it checked

    @see        SRValidatorDelegate
 */
- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagsTaken:(NSEventModifierFlags)aFlags error:(NSError **)outError;

/*!
    Determines whether shortcut is taken in delegate.

    @discussion If delegate does not implement appropriate method, returns immediately.
 */
- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagTakenInDelegate:(NSEventModifierFlags)aFlags error:(NSError **)outError;

/*!
    Determines whether shortcut is taken by system-wide shortcuts.

    @discussion Does not check whether delegate allows or disallows checking in system shortcuts.
 */
- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagsTakenInSystemShortcuts:(NSEventModifierFlags)aFlags error:(NSError **)outError;

/*!
    Determines whether shortcut is taken by application menu item.

    @discussion Does not check whether delegate allows or disallows checking in application menu.
 */
- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlags:(NSEventModifierFlags)aFlags takenInMenu:(NSMenu *)aMenu error:(NSError **)outError;

@end


@protocol SRValidatorDelegate

@optional

/*!
    Asks the delegate if aKeyCode and aFlags are valid.

    @param      aValidator The validator that validates key code and flags.

    @param      aKeyCode Key code to validate.

    @param      aFlags Flags to validate.

    @param      outReason If delegate decides that shortcut is invalid, it may pass here an error message.

    @result     YES if shortcut is valid. Otherwise NO.

    @discussion Implementation of this method by the delegate is optional. If it is not present, checking proceeds as if this method had returned YES.
 */
- (BOOL)shortcutValidator:(SRValidator *)aValidator isKeyCode:(unsigned short)aKeyCode andFlagsTaken:(NSEventModifierFlags)aFlags reason:(NSString **)outReason;

/*!
    Asks the delegate whether validator should check key equivalents of app's menu items.

    @param      aValidator The validator that going to check app's menu items.

    @result     YES if validator should check key equivalents of app's menu items. Otherwise NO.

    @discussion Implementation of this method by the delegate is optional. If it is not present, checking proceeds as if this method had returned YES.
 */
- (BOOL)shortcutValidatorShouldCheckMenu:(SRValidator *)aValidator;

/*!
    Asks the delegate whether it should check system shortcuts.

    @param      aValidator The validator that going to check system shortcuts.

    @result     YES if validator should check system shortcuts. Otherwise NO.

    @discussion Implementation of this method by the delegate is optional. If it is not present, checking proceeds as if this method had returned YES.
 */
- (BOOL)shortcutValidatorShouldCheckSystemShortcuts:(SRValidator *)aValidator;

/*!
    Asks the delegate whether it should use ASCII representation of key code when making error messages.

    @param      aValidator The validator that is about to make an error message.

    @result     YES if validator should use ASCII representation. Otherwise NO.

    @discussion Implementation of this method by the delegate is optional. If it is not present, ASCII representation of key code is used.
 */
- (BOOL)shortcutValidatorShouldUseASCIIStringForKeyCodes:(SRValidator *)aValidator;

@end


@interface NSMenuItem (SRValidator)

/*!
    Returns full path to the menu item. E.g. "Window ➝ Zoom"
 */
- (NSString *)SR_path;

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRValidator.m
================================================
//
//  SRValidator.h
//  ShortcutRecorder
//
//  Copyright 2006-2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors:
//      David Dauer
//      Jesper
//      Jamie Kirkpatrick
//      Andy Kim
//      Silvio Rizzi
//      Ilya Kulakov

#import "SRValidator.h"
#import "SRCommon.h"
#import "SRKeyCodeTransformer.h"


@implementation SRValidator

- (instancetype)initWithDelegate:(NSObject<SRValidatorDelegate> *)aDelegate;
{
    self = [super init];

    if (self)
    {
        _delegate = aDelegate;
    }

    return self;
}

- (instancetype)init
{
    return [self initWithDelegate:nil];
}


#pragma mark Methods

- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagsTaken:(NSEventModifierFlags)aFlags error:(NSError **)outError;
{
    if ([self isKeyCode:aKeyCode andFlagTakenInDelegate:aFlags error:outError])
        return YES;

    if ((![self.delegate respondsToSelector:@selector(shortcutValidatorShouldCheckSystemShortcuts:)] ||
         [self.delegate shortcutValidatorShouldCheckSystemShortcuts:self]) &&
        [self isKeyCode:aKeyCode andFlagsTakenInSystemShortcuts:aFlags error:outError])
    {
        return YES;
    }

    if ((![self.delegate respondsToSelector:@selector(shortcutValidatorShouldCheckMenu:)] ||
         [self.delegate shortcutValidatorShouldCheckMenu:self]) &&
        [self isKeyCode:aKeyCode andFlags:aFlags takenInMenu:[NSApp mainMenu] error:outError])
    {
        return YES;
    }

    return NO;
}

- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagTakenInDelegate:(NSEventModifierFlags)aFlags error:(NSError **)outError
{
    if (self.delegate)
    {
        NSString *delegateReason = nil;
        if ([self.delegate respondsToSelector:@selector(shortcutValidator:isKeyCode:andFlagsTaken:reason:)] &&
            [self.delegate shortcutValidator:self
                                   isKeyCode:aKeyCode
                               andFlagsTaken:aFlags
                                      reason:&delegateReason])
        {
            if (outError)
            {
                BOOL isASCIIOnly = YES;

                if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
                    isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

                NSString *shortcut = isASCIIOnly ? SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode) : SRReadableStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode);
                NSString *failureReason = [NSString stringWithFormat:
                                           SRLoc(@"The key combination \"%@\" can't be used!"),
                                           shortcut];
                NSString *description = [NSString stringWithFormat:
                                         SRLoc(@"The key combination \"%@\" can't be used because %@."),
                                         shortcut,
                                         [delegateReason length] ? delegateReason : @"it's already used"];
                NSDictionary *userInfo = @{
                    NSLocalizedFailureReasonErrorKey : failureReason,
                    NSLocalizedDescriptionKey: description
                };
                *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:userInfo];
            }

            return YES;
        }
    }

    return NO;
}

- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlagsTakenInSystemShortcuts:(NSEventModifierFlags)aFlags error:(NSError **)outError
{
    CFArrayRef s = NULL;
    OSStatus err = CopySymbolicHotKeys(&s);

    if (err != noErr)
        return YES;

    NSArray *symbolicHotKeys = (NSArray *)CFBridgingRelease(s);
    aFlags &= SRCocoaModifierFlagsMask;

    for (NSDictionary *symbolicHotKey in symbolicHotKeys)
    {
        if ((__bridge CFBooleanRef)symbolicHotKey[(__bridge NSString *)kHISymbolicHotKeyEnabled] != kCFBooleanTrue)
            continue;

        unsigned short symbolicHotKeyCode = [symbolicHotKey[(__bridge NSString *)kHISymbolicHotKeyCode] integerValue];

        if (symbolicHotKeyCode == aKeyCode)
        {
            UInt32 symbolicHotKeyFlags = [symbolicHotKey[(__bridge NSString *)kHISymbolicHotKeyModifiers] unsignedIntValue];
            symbolicHotKeyFlags &= SRCarbonModifierFlagsMask;

            if (SRCarbonToCocoaFlags(symbolicHotKeyFlags) == aFlags)
            {
                if (outError)
                {
                    BOOL isASCIIOnly = YES;

                    if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
                        isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

                    NSString *shortcut = isASCIIOnly ? SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode) : SRReadableStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode);
                    NSString *failureReason = [NSString stringWithFormat:
                                               SRLoc(@"The key combination \"%@\" can't be used!"),
                                               shortcut];
                    NSString *description = [NSString stringWithFormat:
                                             SRLoc(@"The key combination \"%@\" can't be used because it's already used by a system-wide keyboard shortcut. If you really want to use this key combination, most shortcuts can be changed in the Keyboard panel in System Preferences."),
                                             shortcut];
                    NSDictionary *userInfo = @{
                        NSLocalizedFailureReasonErrorKey: failureReason,
                        NSLocalizedDescriptionKey: description
                    };
                    *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:userInfo];
                }

                return YES;
            }
        }
    }

    return NO;
}

- (BOOL)isKeyCode:(unsigned short)aKeyCode andFlags:(NSEventModifierFlags)aFlags takenInMenu:(NSMenu *)aMenu error:(NSError **)outError
{
    aFlags &= SRCocoaModifierFlagsMask;

    for (NSMenuItem *menuItem in [aMenu itemArray])
    {
        if (menuItem.hasSubmenu && [self isKeyCode:aKeyCode andFlags:aFlags takenInMenu:menuItem.submenu error:outError])
            return YES;

        NSString *keyEquivalent = menuItem.keyEquivalent;

        if (![keyEquivalent length])
            continue;

        NSEventModifierFlags keyEquivalentModifierMask = menuItem.keyEquivalentModifierMask;

        if (SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(aKeyCode, aFlags, keyEquivalent, keyEquivalentModifierMask))
        {
            if (outError)
            {
                BOOL isASCIIOnly = YES;

                if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
                    isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

                NSString *shortcut = isASCIIOnly ? SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode) : SRReadableStringForCocoaModifierFlagsAndKeyCode(aFlags, aKeyCode);
                NSString *failureReason = [NSString stringWithFormat:SRLoc(@"The key combination \"%@\" can't be used!"), shortcut];
                NSString *description = [NSString stringWithFormat:SRLoc(@"The key combination \"%@\" can't be used because it's already used by the menu item \"%@\"."), shortcut, menuItem.SR_path];
                NSDictionary *userInfo = @{
                    NSLocalizedFailureReasonErrorKey: failureReason,
                    NSLocalizedDescriptionKey: description
                };
                *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:userInfo];
            }

            return YES;
        }
    }

    return NO;
}

@end


@implementation NSMenuItem (SRValidator)

- (NSString *)SR_path
{
    NSMutableArray *items = [NSMutableArray array];
    static const NSUInteger Limit = 1000;
    NSMenuItem *currentMenuItem = self;
    NSUInteger i = 0;

    do
    {
        [items insertObject:currentMenuItem atIndex:0];
        currentMenuItem = currentMenuItem.parentItem;
        ++i;
    }
    while (currentMenuItem && i < Limit);

    NSMutableString *path = [NSMutableString string];

    for (NSMenuItem *menuItem in items)
        [path appendFormat:@"%@➝", menuItem.title];

    if ([path length] > 1)
        [path deleteCharactersInRange:NSMakeRange([path length] - 1, 1)];

    return path;
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Library/ShortcutRecorder.h
================================================
//
//  ShortcutRecorder.h
//  ShortcutRecorder
//  Copyright 2012 Contributors. All rights reserved.
//
//  License: BSD
//
//  Contributors to this file:
//      Jesper
//      Ilya Kulakov

#import <Cocoa/Cocoa.h>
#import <ShortcutRecorder/SRCommon.h>
#import <ShortcutRecorder/SRKeyCodeTransformer.h>
#import <ShortcutRecorder/SRModifierFlagsTransformer.h>
#import <ShortcutRecorder/SRKeyEquivalentTransformer.h>
#import <ShortcutRecorder/SRKeyEquivalentModifierMaskTransformer.h>
#import <ShortcutRecorder/SRValidator.h>
#import <ShortcutRecorder/SRRecorderControl.h>


#ifndef IBInspectable
    #define IBInspectable
#endif

#ifndef IB_DESIGNABLE
    #define IB_DESIGNABLE
#endif

#ifndef NSAppKitVersionNumber10_6
    #define NSAppKitVersionNumber10_6 1038
#endif

#ifndef NSAppKitVersionNumber10_9
    #define NSAppKitVersionNumber10_9 1265
#endif

#ifndef NSEDGEINSETS_DEFINED
    typedef struct NSEdgeInsets {
        CGFloat top;
        CGFloat left;
        CGFloat bottom;
        CGFloat right;
    } NSEdgeInsets;

    NS_INLINE NSEdgeInsets NSEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) {
        NSEdgeInsets e;
        e.top = top;
        e.left = left;
        e.bottom = bottom;
        e.right = right;
        return e;
    }
#endif


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>1.5</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.5</string>
</dict>
</plist>


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey+ShortcutRecorder.h
================================================
//
//  PTHotKey+ShortcutRecorder.h
//  ShortcutRecorder
//
//  Created by Ilya Kulakov on 27.02.11.
//  Copyright 2011 Wireload. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import "PTHotKey.h"


@interface PTHotKey (ShortcutRecorder)

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction;

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction
                        keyUpAction:(SEL)aKeyUpAction;

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction
                        withObject:(id)anObject;
@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey+ShortcutRecorder.m
================================================
//
//  PTHotKey+ShortcutRecorder.m
//  ShortcutRecorder
//
//  Created by Ilya Kulakov on 27.02.11.
//  Copyright 2011 Wireload. All rights reserved.
//

#import "PTHotKey+ShortcutRecorder.h"
#import "SRRecorderControl.h"


@implementation PTHotKey (ShortcutRecorder)

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction
{
    return [PTHotKey hotKeyWithIdentifier:anIdentifier keyCombo:aKeyCombo target:aTarget action:anAction withObject:nil];
}

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction
                        withObject:(id)anObject
{
    NSInteger keyCode = [[aKeyCombo objectForKey:@"keyCode"] integerValue];
    NSUInteger modifiers = SRCocoaToCarbonFlags([[aKeyCombo objectForKey:@"modifierFlags"] unsignedIntegerValue]);
    PTKeyCombo *newKeyCombo = [[PTKeyCombo alloc] initWithKeyCode:keyCode modifiers:modifiers];
    PTHotKey *newHotKey = [[PTHotKey alloc] initWithIdentifier:anIdentifier keyCombo:newKeyCombo];
    [newHotKey setTarget:aTarget];
    [newHotKey setAction:anAction];
    [newHotKey setObject:anObject];
    return newHotKey;
}

+ (PTHotKey *)hotKeyWithIdentifier:(id)anIdentifier
                          keyCombo:(NSDictionary *)aKeyCombo
                            target:(id)aTarget
                            action:(SEL)anAction
                       keyUpAction:(SEL)aKeyUpAction
{				
    PTHotKey *newHotKey = [PTHotKey hotKeyWithIdentifier:anIdentifier
                                                keyCombo:aKeyCombo
                                                  target:aTarget
                                                  action:anAction];
    [newHotKey setKeyUpAction:aKeyUpAction];
    return newHotKey;
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey.h
================================================
//
//  PTHotKey.h
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//
//  Contributors:
// 		Andy Kim

#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>
#import "PTKeyCombo.h"

@interface PTHotKey : NSObject
{
	NSString*		mIdentifier;
	NSString*		mName;
	PTKeyCombo*		mKeyCombo;
	id				mTarget;
    id              mObject;
	SEL				mAction;
    SEL             mKeyUpAction;

	UInt32		    mCarbonHotKeyID;
	EventHotKeyRef	mCarbonEventHotKeyRef;
}

- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo;
- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo withObject: (id)object;
- (id)init;

- (void)setIdentifier: (id)ident;
- (id)identifier;

- (void)setName: (NSString*)name;
- (NSString*)name;

- (void)setKeyCombo: (PTKeyCombo*)combo;
- (PTKeyCombo*)keyCombo;

- (void)setTarget: (id)target;
- (id)target;
- (void)setObject: (id)object;
- (id)object;
- (void)setAction: (SEL)action;
- (SEL)action;
- (void)setKeyUpAction: (SEL)action;
- (SEL)keyUpAction;

- (UInt32)carbonHotKeyID;
- (void)setCarbonHotKeyID: (UInt32)hotKeyID;

- (EventHotKeyRef)carbonEventHotKeyRef;
- (void)setCarbonEventHotKeyRef:(EventHotKeyRef)hotKeyRef;

- (void)invoke;
- (void)uninvoke;

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey.m
================================================
//
//  PTHotKey.m
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//

#import "PTHotKey.h"

#import "PTHotKeyCenter.h"
#import "PTKeyCombo.h"

@implementation PTHotKey

- (id)init
{
    return [self initWithIdentifier: nil keyCombo: nil withObject:nil];
}

- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo
{
    return [self initWithIdentifier: identifier keyCombo: combo withObject:nil];

}

- (id)initWithIdentifier: (id)identifier keyCombo: (PTKeyCombo*)combo withObject: (id)object
{
    self = [super init];

    if( self )
    {
        [self setIdentifier: identifier];
        [self setKeyCombo: combo];
        [self setObject: object];
    }

    return self;
}


- (NSString*)description
{
    return [NSString stringWithFormat: @"<%@: %@, %@>", NSStringFromClass( [self class] ), [self identifier], [self keyCombo]];
}

#pragma mark -

- (void)setIdentifier: (id)ident
{
    mIdentifier = ident;
}

- (id)identifier
{
    return mIdentifier;
}

- (void)setKeyCombo: (PTKeyCombo*)combo
{
    if( combo == nil )
        combo = [PTKeyCombo clearKeyCombo];

    mKeyCombo = combo;
}

- (PTKeyCombo*)keyCombo
{
    return mKeyCombo;
}

- (void)setName: (NSString*)name
{
    mName = name;
}

- (NSString*)name
{
    return mName;
}

- (void)setTarget: (id)target
{
    mTarget = target;
}

- (id)target
{
    return mTarget;
}

- (void)setObject:(id)object
{
    mObject = object;
}

- (id)object
{
    return mObject;
}

- (void)setAction: (SEL)action
{
    mAction = action;
}

- (SEL)action
{
    return mAction;
}

- (void)setKeyUpAction: (SEL)action
{
    mKeyUpAction = action;
}

- (SEL)keyUpAction
{
    return mKeyUpAction;
}

- (UInt32)carbonHotKeyID
{
    return mCarbonHotKeyID;
}

- (void)setCarbonHotKeyID: (UInt32)hotKeyID;
{
    mCarbonHotKeyID = hotKeyID;
}

- (EventHotKeyRef)carbonEventHotKeyRef
{
    return mCarbonEventHotKeyRef;
}

- (void)setCarbonEventHotKeyRef: (EventHotKeyRef)hotKeyRef
{
    mCarbonEventHotKeyRef = hotKeyRef;
}

#pragma mark -

- (void)invoke
{
    if(mAction)
        [NSApp sendAction:mAction to:mTarget from:self];
}

- (void)uninvoke
{
    if(mKeyUpAction)
        [NSApp sendAction:mKeyUpAction to:mTarget from:self];
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKeyCenter.h
================================================
//
//  PTHotKeyCenter.h
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//
//  Contributors:
//      Quentin D. Carnicelli
//      Finlay Dobbie
//      Vincent Pottier
// 		Andy Kim

#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>

@class PTHotKey;

@interface PTHotKeyCenter : NSObject
{
	NSMutableDictionary*	mHotKeys; //Keys are carbon hot key IDs
	BOOL					mEventHandlerInstalled;
	UInt32					mHotKeyCount; // Used to assign new hot key ID
    BOOL                    mIsPaused;
    EventHandlerRef         mEventHandler;
}

+ (PTHotKeyCenter *)sharedCenter;

- (BOOL)registerHotKey: (PTHotKey*)hotKey;
- (void)unregisterHotKey: (PTHotKey*)hotKey;

- (NSArray*)allHotKeys;
- (PTHotKey*)hotKeyWithIdentifier: (id)ident;

- (void)sendEvent: (NSEvent*)event;

- (void)pause;

- (void)resume;

- (BOOL)isPaused;

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKeyCenter.m
================================================
//
//  PTHotKeyCenter.m
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//

#import "PTHotKeyCenter.h"
#import "PTHotKey.h"
#import "PTKeyCombo.h"

@interface PTHotKeyCenter (Private)
- (PTHotKey*)_hotKeyForCarbonHotKey: (EventHotKeyRef)carbonHotKey;
- (PTHotKey*)_hotKeyForCarbonHotKeyID: (EventHotKeyID)hotKeyID;

- (void)_updateEventHandler;
- (void)_hotKeyDown: (PTHotKey*)hotKey;
- (void)_hotKeyUp: (PTHotKey*)hotKey;
static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon );
@end

@implementation PTHotKeyCenter

static PTHotKeyCenter *_sharedHotKeyCenter = nil;

+ (PTHotKeyCenter*)sharedCenter
{
	if( _sharedHotKeyCenter == nil )
	{
		_sharedHotKeyCenter = [[self alloc] init];
	}

	return _sharedHotKeyCenter;
}

- (id)init
{
	self = [super init];

	if( self )
	{
		mHotKeys = [[NSMutableDictionary alloc] init];
	}

	return self;
}


#pragma mark -

- (BOOL)registerHotKey: (PTHotKey*)hotKey
{
    if ( mIsPaused == NO )
    {
        OSStatus err;
        EventHotKeyID hotKeyID;
        EventHotKeyRef carbonHotKey;

        if( [[self allHotKeys] containsObject: hotKey] == YES )
            [self unregisterHotKey: hotKey];

        if( [[hotKey keyCombo] isValidHotKeyCombo] == NO )
            return YES;

        hotKeyID.signature = 'PTHk';
        hotKeyID.id = ++mHotKeyCount;

        err = RegisterEventHotKey(  (SInt32)[[hotKey keyCombo] keyCode],
                                    (UInt32)[[hotKey keyCombo] modifiers],
                                    hotKeyID,
                                    GetEventDispatcherTarget(),
                                    0,
                                    &carbonHotKey );

        if( err )
            return NO;

        [hotKey setCarbonHotKeyID:hotKeyID.id];
        [hotKey setCarbonEventHotKeyRef:carbonHotKey];

        if( hotKey )
            [mHotKeys setObject: hotKey forKey: [NSNumber numberWithInteger:hotKeyID.id]];

        [self _updateEventHandler];
    }
    else
    {
        EventHotKeyID hotKeyID = {'PTHk', ++mHotKeyCount};
        [hotKey setCarbonHotKeyID:hotKeyID.id];

        if( hotKey )
            [mHotKeys setObject: hotKey forKey: [NSNumber numberWithInteger:hotKeyID.id]];
    }
    return YES;
}

- (void)unregisterHotKey: (PTHotKey*)hotKey
{
    if ( mIsPaused == NO )
    {
        EventHotKeyRef carbonHotKey;

        if( [[self allHotKeys] containsObject: hotKey] == NO )
            return;

        carbonHotKey = [hotKey carbonEventHotKeyRef];

        if( carbonHotKey )
        {
            UnregisterEventHotKey( carbonHotKey );
            //Watch as we ignore 'err':

            [mHotKeys removeObjectForKey: [NSNumber numberWithInteger:[hotKey carbonHotKeyID]]];

            [hotKey setCarbonHotKeyID:0];
            [hotKey setCarbonEventHotKeyRef:NULL];

            [self _updateEventHandler];

            //See that? Completely ignored
        }
    }
    else
    {
        [mHotKeys removeObjectForKey: [NSNumber numberWithInteger:[hotKey carbonHotKeyID]]];

        [hotKey setCarbonHotKeyID:0];
        [hotKey setCarbonEventHotKeyRef:NULL];
    }
}

- (NSArray*)allHotKeys
{
	return [mHotKeys allValues];
}

- (PTHotKey*)hotKeyWithIdentifier: (id)ident
{
	NSEnumerator* hotKeysEnum = [[self allHotKeys] objectEnumerator];
	PTHotKey* hotKey;

	if( !ident )
		return nil;

	while( (hotKey = [hotKeysEnum nextObject]) != nil )
	{
		if( [[hotKey identifier] isEqual: ident] )
			return hotKey;
	}

	return nil;
}

#pragma mark -

- (PTHotKey*)_hotKeyForCarbonHotKey: (EventHotKeyRef)carbonHotKeyRef
{
	NSEnumerator *e = [mHotKeys objectEnumerator];
	PTHotKey *hotkey = nil;

	while( (hotkey = [e nextObject]) )
	{
		if( [hotkey carbonEventHotKeyRef] == carbonHotKeyRef )
			return hotkey;
	}

	return nil;
}

- (PTHotKey*)_hotKeyForCarbonHotKeyID: (EventHotKeyID)hotKeyID
{
	return [mHotKeys objectForKey:[NSNumber numberWithInteger:hotKeyID.id]];
}

- (void)_updateEventHandler
{
	if( [mHotKeys count] && mEventHandlerInstalled == NO )
	{
		EventTypeSpec eventSpec[2] = {
			{ kEventClassKeyboard, kEventHotKeyPressed },
			{ kEventClassKeyboard, kEventHotKeyReleased }
		};

		InstallEventHandler( GetEventDispatcherTarget(),
							 (EventHandlerProcPtr)hotKeyEventHandler,
							 2, eventSpec, nil, &mEventHandler);

		mEventHandlerInstalled = YES;
	}
}

- (void)_hotKeyDown: (PTHotKey*)hotKey
{
	[hotKey invoke];
}

- (void)_hotKeyUp: (PTHotKey*)hotKey
{
    [hotKey uninvoke];
}

- (void)sendEvent: (NSEvent*)event
{
	// Not sure why this is needed? - Andy Kim (Aug 23, 2009)

	short subType;
	EventHotKeyRef carbonHotKey;

    if( [event type] == NSEventTypeSystemDefined )
	{
		subType = [event subtype];

		if( subType == 6 ) //6 is hot key down
		{
			carbonHotKey= (EventHotKeyRef)[event data1]; //data1 is our hot key ref
			if( carbonHotKey != nil )
			{
				PTHotKey* hotKey = [self _hotKeyForCarbonHotKey: carbonHotKey];
				[self _hotKeyDown: hotKey];
			}
		}
		else if( subType == 9 ) //9 is hot key up
		{
			carbonHotKey= (EventHotKeyRef)[event data1];
			if( carbonHotKey != nil )
			{
				PTHotKey* hotKey = [self _hotKeyForCarbonHotKey: carbonHotKey];
				[self _hotKeyUp: hotKey];
			}
		}
	}
}

- (OSStatus)sendCarbonEvent: (EventRef)event
{
	OSStatus err;
	EventHotKeyID hotKeyID;
	PTHotKey* hotKey;

	NSAssert( GetEventClass( event ) == kEventClassKeyboard, @"Unknown event class" );

	err = GetEventParameter(	event,
								kEventParamDirectObject,
								typeEventHotKeyID,
								nil,
								sizeof(EventHotKeyID),
								nil,
								&hotKeyID );
	if( err )
		return err;

    	if( hotKeyID.signature != 'PTHk' )
        	return eventNotHandledErr;

    if (hotKeyID.id == 0)
        return eventNotHandledErr;

	hotKey = [self _hotKeyForCarbonHotKeyID:hotKeyID];

	switch( GetEventKind( event ) )
	{
		case kEventHotKeyPressed:
			[self _hotKeyDown: hotKey];
		break;

		case kEventHotKeyReleased:
			[self _hotKeyUp: hotKey];
		break;

		default:
			return eventNotHandledErr;
		break;
	}

	return noErr;
}

- (void)pause
{
    if ( mIsPaused )
        return;

    mIsPaused = YES;
    for (NSNumber *hotKeyID in mHotKeys)
    {
        PTHotKey *hotKey = [mHotKeys objectForKey:hotKeyID];
        EventHotKeyRef carbonHotKey = [hotKey carbonEventHotKeyRef];
        UnregisterEventHotKey( carbonHotKey );
        [hotKey setCarbonEventHotKeyRef:NULL];
    }
    if (mEventHandler != NULL)
    {
        RemoveEventHandler(mEventHandler);
        mEventHandler = NULL;
        mEventHandlerInstalled = NO;
    }
}

- (void)resume
{
    if ( mIsPaused == NO)
        return;

    mIsPaused = NO;
    for (NSNumber *hotKeyIDNumber in mHotKeys)
    {
        PTHotKey *hotKey = [mHotKeys objectForKey:hotKeyIDNumber];
        EventHotKeyRef carbonHotKey = NULL;
        EventHotKeyID hotKeyID;
        hotKeyID.signature = 'PTHk';
        hotKeyID.id = [hotKey carbonHotKeyID];
        RegisterEventHotKey(  (SInt32)[[hotKey keyCombo] keyCode],
                              (UInt32)[[hotKey keyCombo] modifiers],
                              hotKeyID,
                              GetEventDispatcherTarget(),
                              0,
                              &carbonHotKey );
        [hotKey setCarbonEventHotKeyRef:carbonHotKey];
    }
    [self _updateEventHandler];
}

- (BOOL)isPaused
{
    return mIsPaused;
}

static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon )
{
    return [[PTHotKeyCenter sharedCenter] sendCarbonEvent: inEvent];
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCodeTranslator.h
================================================
//
//  PTKeyCodeTranslator.h
//  Chercher
//
//  Created by Finlay Dobbie on Sat Oct 11 2003.
//  Copyright (c) 2003 Cliché Software. All rights reserved.
//

#import <Carbon/Carbon.h>

@interface PTKeyCodeTranslator : NSObject
{
    TISInputSourceRef	keyboardLayout;
    const UCKeyboardLayout	*uchrData;
    UInt32		keyTranslateState;
    UInt32		deadKeyState;
}

+ (id)currentTranslator;

- (id)initWithKeyboardLayout:(TISInputSourceRef)aLayout;
- (NSString *)translateKeyCode:(short)keyCode;

- (TISInputSourceRef)keyboardLayout;

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCodeTranslator.m
================================================
//
//  PTKeyCodeTranslator.m
//  Chercher
//
//  Created by Finlay Dobbie on Sat Oct 11 2003.
//  Copyright (c) 2003 Cliché Software. All rights reserved.
//

#import "PTKeyCodeTranslator.h"


@implementation PTKeyCodeTranslator

+ (id)currentTranslator
{
    static PTKeyCodeTranslator *current = nil;
    TISInputSourceRef currentLayout = TISCopyCurrentKeyboardLayoutInputSource();

    if (current == nil) {
        current = [[PTKeyCodeTranslator alloc] initWithKeyboardLayout:currentLayout];
    } else if ([current keyboardLayout] != currentLayout) {
        current = [[PTKeyCodeTranslator alloc] initWithKeyboardLayout:currentLayout];
    }

	CFRelease(currentLayout);

    return current;
}

- (id)initWithKeyboardLayout:(TISInputSourceRef)aLayout
{
    if ((self = [super init]) != nil) {
        keyboardLayout = aLayout;

		CFRetain(keyboardLayout);

        CFDataRef uchr = TISGetInputSourceProperty( keyboardLayout , kTISPropertyUnicodeKeyLayoutData );
        uchrData = ( const UCKeyboardLayout* )CFDataGetBytePtr(uchr);
    }

    return self;
}

- (void)dealloc
{

	CFRelease(keyboardLayout);

}

- (NSString *)translateKeyCode:(short)keyCode {
    UniCharCount maxStringLength = 4, actualStringLength;
    UniChar unicodeString[4];
    UCKeyTranslate( uchrData, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, maxStringLength, &actualStringLength, unicodeString );
    return [NSString stringWithCharacters:unicodeString length:1];
}

- (TISInputSourceRef)keyboardLayout {
    return keyboardLayout;
}

- (NSString *)description {
    NSString *kind;
    kind = @"uchr";

    NSString *layoutName;
    layoutName = (__bridge NSString *)(TISGetInputSourceProperty( keyboardLayout, kTISPropertyLocalizedName ));
    return [NSString stringWithFormat:@"PTKeyCodeTranslator layout=%@ (%@)", layoutName, kind];
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCombo.h
================================================
//
//  PTKeyCombo.h
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface PTKeyCombo : NSObject <NSCopying>
{
	NSInteger	mKeyCode;
	NSUInteger	mModifiers;
}

+ (id)clearKeyCombo;
+ (id)keyComboWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers;
- (id)initWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers;

- (id)initWithPlistRepresentation: (id)plist;
- (id)plistRepresentation;

- (BOOL)isEqual: (PTKeyCombo*)combo;

- (NSInteger)keyCode;
- (NSUInteger)modifiers;

- (BOOL)isClearCombo;
- (BOOL)isValidHotKeyCombo;

@end


@interface PTKeyCombo (UserDisplayAdditions)
- (NSString*)keyCodeString;
- (NSUInteger)modifierMask;
@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCombo.m
================================================
//
//  PTKeyCombo.m
//  Protein
//
//  Created by Quentin Carnicelli on Sat Aug 02 2003.
//  Copyright (c) 2003 Quentin D. Carnicelli. All rights reserved.
//

#import "PTKeyCombo.h"
#import "PTKeyCodeTranslator.h"

@implementation PTKeyCombo

+ (id)clearKeyCombo
{
	return [self keyComboWithKeyCode: -1 modifiers: -1];
}

+ (id)keyComboWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers
{
	return [[self alloc] initWithKeyCode: keyCode modifiers: modifiers];
}

- (id)initWithKeyCode: (NSInteger)keyCode modifiers: (NSUInteger)modifiers
{
	self = [super init];

	if( self )
	{
        switch ( keyCode )
        {
            case kVK_F1:
            case kVK_F2:
            case kVK_F3:
            case kVK_F4:
            case kVK_F5:
            case kVK_F6:
            case kVK_F7:
            case kVK_F8:
            case kVK_F9:
            case kVK_F10:
            case kVK_F11:
            case kVK_F12:
            case kVK_F13:
            case kVK_F14:
            case kVK_F15:
            case kVK_F16:
            case kVK_F17:
            case kVK_F18:
            case kVK_F19:
            case kVK_F20:
                mModifiers = modifiers | NSEventModifierFlagFunction;
                break;
            default:
                mModifiers = modifiers;
                break;
        }

		mKeyCode = keyCode;
	}

	return self;
}

- (id)initWithPlistRepresentation: (id)plist
{
	int keyCode, modifiers;

	if( !plist || ![plist count] )
	{
		keyCode = -1;
		modifiers = -1;
	}
	else
	{
		keyCode = [[plist objectForKey: @"keyCode"] intValue];
		if( keyCode < 0 ) keyCode = -1;

		modifiers = [[plist objectForKey: @"modifiers"] intValue];
		if( modifiers <= 0 ) modifiers = -1;
	}

	return [self initWithKeyCode: keyCode modifiers: modifiers];
}

- (id)plistRepresentation
{
	return [NSDictionary dictionaryWithObjectsAndKeys:
				[NSNumber numberWithInteger: [self keyCode]], @"keyCode",
				[NSNumber numberWithInteger: [self modifiers]], @"modifiers",
				nil];
}

- (id)copyWithZone:(NSZone*)zone;
{
	return self;
}

- (BOOL)isEqual: (PTKeyCombo*)combo
{
	return	[self keyCode] == [combo keyCode] &&
			[self modifiers] == [combo modifiers];
}

#pragma mark -

- (NSInteger)keyCode
{
	return mKeyCode;
}

- (NSUInteger)modifiers
{
	return mModifiers;
}

- (BOOL)isValidHotKeyCombo
{
	return mKeyCode >= 0 && mModifiers > 0;
}

- (BOOL)isClearCombo
{
	return mKeyCode == -1 && mModifiers == 0;
}

@end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/README.md
================================================
ShortcutRecorder 2
====================
![pre-Yosemite ShortcutRecorder Preview](Demo/example.png)
![Yosemite ShortcutRecorder Preview](Demo/example-yosemite.png)

The only user interface control to record shortcuts. For Mac OS X 10.6+, 64bit.

- :microscope: Support for Xcode 6 Quick Help
- :microscope: Support for Xcode 6 Interface Builder integration
- Fresh Look & Feel (brought to you by [Wireload](http://wireload.net) and [John Wells](https://github.com/jwells89))
- With Retina support
- Auto Layout ready
- Correct drawing on Layer-backed and Layer-hosted views
- Accessibility for people with disabilities
- Revised codebase with Automatic Reference Counting support
- Translated into 24 languages

Includes framework to set global shortcuts (PTHotKey).

Get Sources
-----------
The preferred way to add the ShortcutRecorder to your project is to use git submodules:
`git submodule add git://github.com/Kentzo/ShortcutRecorder.git`
You can download sources from the site as well.

Integrate into your project
---------------------------
First, add ShortcutRecorder.xcodeproj to your workspace via Xcode ([Apple docs](https://developer.apple.com/library/mac/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)). Don't have a workspace? No problem, just add ShortcutRecorder.xcodeproj via the "Add Files to" dialog.

Next step is to ensure your target is linked against the ShortcutRecorder or/and PTHotKey frameworks ([Apple docs](http://developer.apple.com/library/ios/#recipes/xcode_help-project_editor/Articles/AddingaLibrarytoaTarget.html#//apple_ref/doc/uid/TP40010155-CH17)). Desired frameworks will be listed under *Workspace*.

Now it's time to make frameworks part of your app. To do this, you need to add custom Build Phase ([Apple docs](http://developer.apple.com/library/ios/#recipes/xcode_help-project_editor/Articles/CreatingaCopyFilesBuildPhase.html)). Remember to set *Destination* to *Frameworks* and clean up *Subpath*.

Finally, ensure your app will find frameworks upon start. Open Build Settings of your target, look up *Runtime Search Paths*. Add `@executable_path/../Frameworks` to the list of paths.

Add control in Interface Builder
--------------------------------
Since Xcode 4 Apple removed Interface Builder Plugins. You can only use it to add and position/resize ShortcutRecorder control. To do this, add Custom View and set its class to SRRecorderControl.

SRRecorderControl has fixed height of 25 points so ensure you do not use autoresizing masks/layout rules which allows vertical resizing. I recommend you to pin height in case you're using Auto Layout.

Usage
-----
First, we want to keep value of the control across relaunches of the app. We can simply achieve this by using NSUserDefaultsController and bindings:

    [self.pingShortcutRecorder bind:NSValueBinding
                           toObject:[NSUserDefaultsController sharedUserDefaultsController]
                        withKeyPath:@"values.ping"
                            options:nil];

The value can be used to set key equivalent of NSMenuItem or NSButton. It can also be used to register a global shortcut.

Setting key equivalent of NSMenuItem using bindings:

    [self.pingItem bind:@"keyEquivalent"
               toObject:defaults
            withKeyPath:@"values.ping"
                options:@{NSValueTransformerBindingOption: [SRKeyEquivalentTransformer new]}];
    [self.pingItem bind:@"keyEquivalentModifierMask"
               toObject:defaults
            withKeyPath:@"values.ping"
                options:@{NSValueTransformerBindingOption: [SRKeyEquivalentModifierMaskTransformer new]}];

Setting key equivalent of NSButton using bindings:

    [self.pingButton bind:@"keyEquivalent"
                 toObject:defaults
              withKeyPath:@"values.ping"
                  options:@{NSValueTransformerBindingOption: [SRKeyEquivalentTransformer new]}];
    [self.pingButton bind:@"keyEquivalentModifierMask"
                 toObject:defaults
              withKeyPath:@"values.ping"
                  options:@{NSValueTransformerBindingOption: [SRKeyEquivalentModifierMaskTransformer new]}];

Setting global shortcut using PTHotKeyCenter:

    PTHotKeyCenter *hotKeyCenter = [PTHotKeyCenter sharedCenter];
    PTHotKey *oldHotKey = [hotKeyCenter hotKeyWithIdentifier:aKeyPath];
    [hotKeyCenter unregisterHotKey:oldHotKey];

    PTHotKey *newHotKey = [PTHotKey hotKeyWithIdentifier:aKeyPath
                                                keyCombo:newShortcut
                                                  target:self
                                                  action:@selector(ping:)];
    [hotKeyCenter registerHotKey:newHotKey];

Key Equivalents and Keyboard Layout
----------------------------------------------------
While ShortcutRecorder keeps your shortcuts as combination of *key code* and modifier masks, key equivalents are expressed using *key character* and modifier mask. The difference is that position of key code on keyboard does not depend on current keyboard layout while position of key character does.

ShortcutRecorder includes two special transformers to simplify binding to the key equivalents of NSMenuItem and NSButton:

- SRKeyEquivalentTransformer
- SRKeyEquivalentModifierMaskTransformer

SRKeyEquivalentTransformer uses ASCII keyboard layout to convert key code into character, therefore resulting character does not depend on keyboard layout.
The drawback is that position of the character on keyboard may change depending on layout and used modifier keys (primarly Option and Shift).

NSButton
--------
If you're going to bind ShortcutRecorder to key equivalent of NSButton, I encourage you to require `NSCommandKeyMask`.
This is because NSButton handles key equivalents very strange. Rather than investigating full information of the keyboard event, it just asks for `charactersIgnoringModifiers`
and compares returned value with its `keyEquivalent`. Unfortunately, Cocoa returns layout-independent (ASCII) representation of characters only when NSCommandKeyMask is set.
If it's not set, assigned shortcut likely won't work with other layouts.

Questions
---------
Still have questions? [Create an issue](https://github.com/Kentzo/ShortcutRecorder/issues/new) immediately and feel free to ping me.

Paid Support
------------
If functional you need is missing but you're ready to pay for it, feel free to contact me. If not, create an issue anyway, I'll take a look as soon as I can.


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/Resources/LICENSE.txt
================================================
Copyright (c) 2006, contributors to ShortcutRecorder. (See the contributors listed in detail later in the file, or see <http://wafflesoftware.net/shortcut/contributors/>.)

All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * The name of the contributors may not be used to endorse or promote 
      products derived from this software without specific prior written
      permission.

THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=====================================================================

Contributors to Shortcut Recorder, in no order in particular:
Jesper, waffle software, <wootest+shortcutrecorder@gmail.com>. Initial idea and concept, first shot at implementation using NSView.
David Dauer, <david@daviddauer.de>. Refinement, cleaner reimplementation, documentation, IB Palette.
Jamie Kirkpatrick, Kirk Consulting Ltd, <jkp@kirkconsulting.co.uk>.  Further modularisation and re-factoring, and general bug fixes.
Ilya Kulakov, <kulakov.ilya@gmail.com>. ShortcutRecorder 2.0 and further support.
Alexander Ljungberg, <aljungberg@wireload.net>. Graphics for ShortcutRecorder 2.0

=====================================================================

Some rights reserved: <http://creativecommons.org/licenses/by/3.0/>

For more information, visit <http://blog.oofn.net/projects/misc/>


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.podspec
================================================
Pod::Spec.new do |s|
  s.name = 'ShortcutRecorder'
  s.homepage = 'https://github.com/Kentzo/ShortcutRecorder'
  s.summary = ''
  s.version = '2.17'
  s.source = { :git => 'git://github.com/Kentzo/ShortcutRecorder.git', :branch => 'master' }
  s.author = { 'Ilya Kulakov' => 'kulakov.ilya@gmail.com' }
  s.frameworks = 'Carbon', 'Cocoa'
  s.platform = :osx, "10.6"

  s.subspec 'Core' do |core|
    core.source_files = 'Library/*.{h,m}'
    core.resource_bundles = { "ShortcutRecorder" => ['Resources/*.lproj', 'Resources/*.png'] }
    core.requires_arc = true
    core.prefix_header_file = 'Library/Prefix.pch'
  end

  s.subspec 'PTHotKey' do |hotkey|
    hotkey.source_files = 'PTHotKey/*.{h,m}'
    hotkey.requires_arc = false
    hotkey.dependency 'ShortcutRecorder/Core'
  end
end


================================================
FILE: Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		939837950DA429EC007F53F3 /* SRRecorderControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B8E29C109CDB9360085E9ED /* SRRecorderControl.m */; };
		939837980DA429EC007F53F3 /* SRKeyCodeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 74C3670D0A246B4900B69171 /* SRKeyCodeTransformer.m */; };
		939837990DA429EC007F53F3 /* SRValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 74C3670F0A246B4900B69171 /* SRValidator.m */; };
		9398379A0DA429EC007F53F3 /* SRCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 74C367110A246B4900B69171 /* SRCommon.m */; };
		939839390DA4350B007F53F3 /* ShortcutRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 939837B50DA42DFB007F53F3 /* ShortcutRecorder.h */; settings = {ATTRIBUTES = (Public, ); }; };
		9398393B0DA4350B007F53F3 /* SRRecorderControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B8E29C009CDB9360085E9ED /* SRRecorderControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
		9398393E0DA4350B007F53F3 /* SRKeyCodeTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C3670C0A246B4900B69171 /* SRKeyCodeTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
		9398393F0DA4350B007F53F3 /* SRValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C3670E0A246B4900B69171 /* SRValidator.h */; settings = {ATTRIBUTES = (Public, ); }; };
		939839400DA4350B007F53F3 /* SRCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C367100A246B4900B69171 /* SRCommon.h */; settings = {ATTRIBUTES = (Public, ); }; };
		BA547C271A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-left.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C011A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-left.png */; };
		BA547C281A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C021A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-left@2x.png */; };
		BA547C291A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-middle.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C031A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-middle.png */; };
		BA547C2A1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-middle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C041A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-middle@2x.png */; };
		BA547C2B1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-right.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C051A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-right.png */; };
		BA547C2C1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C061A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-blue-highlighted-right@2x.png */; };
		BA547C2D1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-left.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C071A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-left.png */; };
		BA547C2E1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C081A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-left@2x.png */; };
		BA547C2F1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-middle.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C091A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-middle.png */; };
		BA547C301A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-middle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0A1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-middle@2x.png */; };
		BA547C311A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-right.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0B1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-right.png */; };
		BA547C321A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0C1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-disabled-right@2x.png */; };
		BA547C331A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-left.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0D1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-left.png */; };
		BA547C341A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0E1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-left@2x.png */; };
		BA547C351A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-middle.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C0F1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-middle.png */; };
		BA547C361A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-middle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C101A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-middle@2x.png */; };
		BA547C371A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-right.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C111A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-right.png */; };
		BA547C381A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C121A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-editing-right@2x.png */; };
		BA547C391A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-left.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C131A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-left.png */; };
		BA547C3A1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C141A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-left@2x.png */; };
		BA547C3B1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-middle.png in Resources */ = {isa = PBXBuildFile; fileRef = BA547C151A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-middle.png */; };
		BA547C3C1A5FD45B00C45C31 /* shortcut-recorder-yosemite-bezel-graphite-highlighted-middle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef =
Download .txt
gitextract_ww47k156/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .swiftformat
├── .swiftlint.yml
├── .travis.yml
├── Archive/
│   └── New Icons/
│       └── Older Icons/
│           ├── New Icons/
│           │   └── NewIcon.xcf
│           └── Old Icons/
│               └── ClockerIcon.xcf
├── CLAUDE.md
├── Clocker/
│   ├── AppDelegate.swift
│   ├── Clocker/
│   │   ├── Clocker-Info.plist
│   │   ├── Clocker-Prefix.pch
│   │   ├── Clocker.entitlements
│   │   ├── LocationController.swift
│   │   ├── MainMenu.xib
│   │   ├── ShortcutRecorder-master/
│   │   │   ├── .gitignore
│   │   │   ├── LICENSE.md
│   │   │   ├── Library/
│   │   │   │   ├── Info.plist
│   │   │   │   ├── Prefix.pch
│   │   │   │   ├── SRCommon.h
│   │   │   │   ├── SRCommon.m
│   │   │   │   ├── SRKeyCodeTransformer.h
│   │   │   │   ├── SRKeyCodeTransformer.m
│   │   │   │   ├── SRKeyEquivalentModifierMaskTransformer.h
│   │   │   │   ├── SRKeyEquivalentModifierMaskTransformer.m
│   │   │   │   ├── SRKeyEquivalentTransformer.h
│   │   │   │   ├── SRKeyEquivalentTransformer.m
│   │   │   │   ├── SRModifierFlagsTransformer.h
│   │   │   │   ├── SRModifierFlagsTransformer.m
│   │   │   │   ├── SRRecorderControl.h
│   │   │   │   ├── SRRecorderControl.m
│   │   │   │   ├── SRValidator.h
│   │   │   │   ├── SRValidator.m
│   │   │   │   └── ShortcutRecorder.h
│   │   │   ├── PTHotKey/
│   │   │   │   ├── Info.plist
│   │   │   │   ├── PTHotKey+ShortcutRecorder.h
│   │   │   │   ├── PTHotKey+ShortcutRecorder.m
│   │   │   │   ├── PTHotKey.h
│   │   │   │   ├── PTHotKey.m
│   │   │   │   ├── PTHotKeyCenter.h
│   │   │   │   ├── PTHotKeyCenter.m
│   │   │   │   ├── PTKeyCodeTranslator.h
│   │   │   │   ├── PTKeyCodeTranslator.m
│   │   │   │   ├── PTKeyCombo.h
│   │   │   │   └── PTKeyCombo.m
│   │   │   ├── README.md
│   │   │   ├── Resources/
│   │   │   │   ├── LICENSE.txt
│   │   │   │   ├── ShorcutRecorder Yosemite.sketch
│   │   │   │   ├── ar.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ca.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── cs.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── de.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── el.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── en.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── es-MX.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── es.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── fr.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── it.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ja.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ko.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── nb.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── nl.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pl.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pt-BR.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── pt.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ro.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── ru.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── sk.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── sv.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── th.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── tr.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   ├── zh-Hans.lproj/
│   │   │   │   │   └── ShortcutRecorder.strings
│   │   │   │   └── zh-Hant.lproj/
│   │   │   │       └── ShortcutRecorder.strings
│   │   │   ├── ShortcutRecorder.podspec
│   │   │   └── ShortcutRecorder.xcodeproj/
│   │   │       ├── project.pbxproj
│   │   │       └── xcshareddata/
│   │   │           └── xcschemes/
│   │   │               ├── PTHotKey.framework.xcscheme
│   │   │               └── ShortcutRecorder.framework.xcscheme
│   │   ├── ar.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ca.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── com.abhishek.ClockerHelper.plist
│   │   ├── de.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── en.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   ├── Localizable.strings
│   │   │   └── Panel.xib
│   │   ├── es.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── fr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── hi.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── hr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── it.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ja.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── ko.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── main.m
│   │   ├── nl.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── pl.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── pt-BR.lproj/
│   │   │   └── Localizable.strings
│   │   ├── pt-PT.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── ru.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── tr.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   ├── uk.lproj/
│   │   │   └── Localizable.strings
│   │   ├── zh-Hans.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Localizable.strings
│   │   └── zh-Hant.lproj/
│   │       └── Localizable.strings
│   ├── Clocker-Bridging-Header.h
│   ├── Clocker.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   ├── contents.xcworkspacedata
│   │   │   ├── xcshareddata/
│   │   │   │   ├── Clocker.xcscmblueprint
│   │   │   │   ├── IDEWorkspaceChecks.plist
│   │   │   │   └── WorkspaceSettings.xcsettings
│   │   │   └── xcuserdata/
│   │   │       ├── abhishek_banthia.xcuserdatad/
│   │   │       │   └── WorkspaceSettings.xcsettings
│   │   │       ├── abhishekbanthia.xcuserdatad/
│   │   │       │   └── IDEFindNavigatorScopes.plist
│   │   │       └── ban.xcuserdatad/
│   │   │           └── IDEFindNavigatorScopes.plist
│   │   ├── xcshareddata/
│   │   │   ├── IDETemplateMacros.plist
│   │   │   └── xcschemes/
│   │   │       ├── Clocker.xcscheme
│   │   │       └── Tests.xcscheme
│   │   └── xcuserdata/
│   │       ├── abhi.xcuserdatad/
│   │       │   └── xcschemes/
│   │       │       └── xcschememanagement.plist
│   │       ├── abhishek_banthia.xcuserdatad/
│   │       │   └── xcschemes/
│   │       │       ├── Clocker.xcscheme
│   │       │       ├── ClockerHelper.xcscheme
│   │       │       └── xcschememanagement.plist
│   │       ├── abhishekbanthia.xcuserdatad/
│   │       │   ├── xcdebugger/
│   │       │   │   └── Breakpoints_v2.xcbkptlist
│   │       │   └── xcschemes/
│   │       │       ├── ClockerHelper.xcscheme
│   │       │       └── xcschememanagement.plist
│   │       └── ban.xcuserdatad/
│   │           ├── xcdebugger/
│   │           │   └── Breakpoints_v2.xcbkptlist
│   │           └── xcschemes/
│   │               └── xcschememanagement.plist
│   ├── ClockerHelper/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   └── Main.storyboard
│   │   ├── ClockerHelper.entitlements
│   │   ├── Info.plist
│   │   ├── de.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Main.strings
│   │   ├── main.m
│   │   ├── ru.lproj/
│   │   │   ├── InfoPlist.strings
│   │   │   └── Main.strings
│   │   └── zh-Hans.lproj/
│   │       ├── InfoPlist.strings
│   │       └── Main.strings
│   ├── ClockerUITests/
│   │   ├── AboutUsTests.swift
│   │   ├── ClockerUITests-Bridging-Header.h
│   │   ├── ClockerUITests.m
│   │   ├── CopyToClipboardTests.swift
│   │   ├── FloatingWindowTests.swift
│   │   ├── Info.plist
│   │   ├── NetworkDisconnectionTests.swift
│   │   ├── OnboardingSearchTests.swift
│   │   ├── OnboardingTests.swift
│   │   ├── PanelTests.swift
│   │   ├── PermissionsTests.swift
│   │   ├── PreferencesTest.swift
│   │   ├── ReviewTests.swift
│   │   ├── ShortcutTests.swift
│   │   ├── de.lproj/
│   │   │   └── InfoPlist.strings
│   │   ├── ru.lproj/
│   │   │   └── InfoPlist.strings
│   │   └── zh-Hans.lproj/
│   │       └── InfoPlist.strings
│   ├── ClockerUnitTests/
│   │   ├── AppDelegateTests.swift
│   │   ├── ClockerUnitTests.swift
│   │   ├── DateFormatterManagerTests.swift
│   │   ├── EventInfoTests.swift
│   │   ├── Info.plist
│   │   ├── ReviewControllerTests.swift
│   │   ├── SearchDataSourceTests.swift
│   │   ├── StandardMenubarHandlerTests.swift
│   │   └── ThemerTests.swift
│   ├── CoreLoggerKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   ├── Sources/
│   │   │   └── CoreLoggerKit/
│   │   │       └── Logger.swift
│   │   └── Tests/
│   │       ├── CoreLoggerKitTests/
│   │       │   ├── CoreLoggerKitTests.swift
│   │       │   └── XCTestManifests.swift
│   │       └── LinuxMain.swift
│   ├── CoreModelKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   ├── Sources/
│   │   │   └── CoreModelKit/
│   │   │       ├── SearchResults.swift
│   │   │       └── TimezoneData.swift
│   │   └── Tests/
│   │       ├── CoreModelKitTests/
│   │       │   ├── TimezoneDataEqualityTests.swift
│   │       │   └── XCTestManifests.swift
│   │       └── LinuxMain.swift
│   ├── Dependencies/
│   │   ├── Date Additions/
│   │   │   ├── Constants.swift
│   │   │   ├── Date+Bundle.swift
│   │   │   ├── Date+Comparators.swift
│   │   │   ├── Date+Components.swift
│   │   │   ├── Date+Format.swift
│   │   │   ├── Date+Inits.swift
│   │   │   ├── Date+Manipulations.swift
│   │   │   ├── Date+TimeAgo.swift
│   │   │   ├── DateTools.bundle/
│   │   │   │   ├── am.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ar.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── bg.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ca.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── cs.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── cy.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── da.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── de.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── en.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── es.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── eu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── fi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── fr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── gre.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── gu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── he.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── hu.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── id.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── is.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── it.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ja.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ko.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── lv.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ms.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── nb.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── nl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pt-PT.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── pt.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ro.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── ru.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── sk.lproj/
│   │   │   │   │   └── NSDateTimeAgo.strings
│   │   │   │   ├── sl.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── sv.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── th.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── tr.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── uk.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── vi.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   ├── zh-Hans.lproj/
│   │   │   │   │   └── DateTools.strings
│   │   │   │   └── zh-Hant.lproj/
│   │   │   │       └── DateTools.strings
│   │   │   ├── Enums.swift
│   │   │   ├── Integer+DateTools.swift
│   │   │   └── TimeChunk.swift
│   │   ├── Solar.swift
│   │   └── iVersion/
│   │       ├── iVersion.bundle/
│   │       │   ├── da.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── de.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── el.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── en-GB.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── en.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── es.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── fr.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── it.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── ja.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── pt-PT.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── pt.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── ru.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── tr.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   ├── zh-Hans.lproj/
│   │       │   │   └── Localizable.strings
│   │       │   └── zh-Hant.lproj/
│   │       │       └── Localizable.strings
│   │       ├── iVersion.h
│   │       └── iVersion.m
│   ├── Events and Reminders/
│   │   ├── CalendarHandler.swift
│   │   ├── EventCenter.swift
│   │   └── RemindersHandler.swift
│   ├── Firebase.h
│   ├── Frameworks/
│   │   └── Firebase/
│   │       ├── FirebaseCore.framework/
│   │       │   ├── FirebaseCore
│   │       │   ├── Headers/
│   │       │   │   ├── FIRApp.h
│   │       │   │   ├── FIRConfiguration.h
│   │       │   │   ├── FIRLoggerLevel.h
│   │       │   │   ├── FIROptions.h
│   │       │   │   ├── FIRVersion.h
│   │       │   │   └── FirebaseCore.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseCoreDiagnostics.framework/
│   │       │   ├── FirebaseCoreDiagnostics
│   │       │   ├── Headers/
│   │       │   │   ├── FIRCoreDiagnostics.h
│   │       │   │   └── FirebaseCoreDiagnostics-umbrella.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseCrashlytics.framework/
│   │       │   ├── FirebaseCrashlytics
│   │       │   ├── Headers/
│   │       │   │   ├── FIRCrashlytics.h
│   │       │   │   ├── FIRCrashlyticsReport.h
│   │       │   │   ├── FIRExceptionModel.h
│   │       │   │   ├── FIRStackFrame.h
│   │       │   │   └── FirebaseCrashlytics.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseDatabase.framework/
│   │       │   ├── FirebaseDatabase
│   │       │   ├── Headers/
│   │       │   │   ├── FIRDataEventType.h
│   │       │   │   ├── FIRDataSnapshot.h
│   │       │   │   ├── FIRDatabase.h
│   │       │   │   ├── FIRDatabaseQuery.h
│   │       │   │   ├── FIRDatabaseReference.h
│   │       │   │   ├── FIRMutableData.h
│   │       │   │   ├── FIRServerValue.h
│   │       │   │   ├── FIRTransactionResult.h
│   │       │   │   └── FirebaseDatabase.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── FirebaseInstallations.framework/
│   │       │   ├── FirebaseInstallations
│   │       │   ├── Headers/
│   │       │   │   ├── FIRInstallations.h
│   │       │   │   ├── FIRInstallationsAuthTokenResult.h
│   │       │   │   ├── FIRInstallationsErrors.h
│   │       │   │   └── FirebaseInstallations.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── GoogleDataTransport.framework/
│   │       │   ├── GoogleDataTransport
│   │       │   ├── Headers/
│   │       │   │   ├── GDTCORClock.h
│   │       │   │   ├── GDTCORConsoleLogger.h
│   │       │   │   ├── GDTCOREndpoints.h
│   │       │   │   ├── GDTCOREvent.h
│   │       │   │   ├── GDTCOREventDataObject.h
│   │       │   │   ├── GDTCOREventTransformer.h
│   │       │   │   ├── GDTCORTargets.h
│   │       │   │   ├── GDTCORTransport.h
│   │       │   │   └── GoogleDataTransport.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── GoogleUtilities.framework/
│   │       │   ├── GoogleUtilities
│   │       │   ├── Headers/
│   │       │   │   ├── GULAppDelegateSwizzler.h
│   │       │   │   ├── GULAppEnvironmentUtil.h
│   │       │   │   ├── GULApplication.h
│   │       │   │   ├── GULHeartbeatDateStorable.h
│   │       │   │   ├── GULHeartbeatDateStorage.h
│   │       │   │   ├── GULHeartbeatDateStorageUserDefaults.h
│   │       │   │   ├── GULKeychainStorage.h
│   │       │   │   ├── GULKeychainUtils.h
│   │       │   │   ├── GULLogger.h
│   │       │   │   ├── GULLoggerLevel.h
│   │       │   │   ├── GULMutableDictionary.h
│   │       │   │   ├── GULNSData+zlib.h
│   │       │   │   ├── GULNetwork.h
│   │       │   │   ├── GULNetworkConstants.h
│   │       │   │   ├── GULNetworkLoggerProtocol.h
│   │       │   │   ├── GULNetworkMessageCode.h
│   │       │   │   ├── GULNetworkURLSession.h
│   │       │   │   ├── GULReachabilityChecker.h
│   │       │   │   ├── GULSceneDelegateSwizzler.h
│   │       │   │   ├── GULSecureCoding.h
│   │       │   │   ├── GULURLSessionDataResponse.h
│   │       │   │   ├── GULUserDefaults.h
│   │       │   │   ├── GoogleUtilities-umbrella.h
│   │       │   │   └── NSURLSession+GULPromises.h
│   │       │   ├── Info.plist
│   │       │   └── Modules/
│   │       │       └── module.modulemap
│   │       ├── PromisesObjC.framework/
│   │       │   ├── Headers/
│   │       │   │   ├── FBLPromise+All.h
│   │       │   │   ├── FBLPromise+Always.h
│   │       │   │   ├── FBLPromise+Any.h
│   │       │   │   ├── FBLPromise+Async.h
│   │       │   │   ├── FBLPromise+Await.h
│   │       │   │   ├── FBLPromise+Catch.h
│   │       │   │   ├── FBLPromise+Delay.h
│   │       │   │   ├── FBLPromise+Do.h
│   │       │   │   ├── FBLPromise+Race.h
│   │       │   │   ├── FBLPromise+Recover.h
│   │       │   │   ├── FBLPromise+Reduce.h
│   │       │   │   ├── FBLPromise+Retry.h
│   │       │   │   ├── FBLPromise+Testing.h
│   │       │   │   ├── FBLPromise+Then.h
│   │       │   │   ├── FBLPromise+Timeout.h
│   │       │   │   ├── FBLPromise+Validate.h
│   │       │   │   ├── FBLPromise+Wrap.h
│   │       │   │   ├── FBLPromise.h
│   │       │   │   ├── FBLPromiseError.h
│   │       │   │   ├── FBLPromises.h
│   │       │   │   └── PromisesObjC-umbrella.h
│   │       │   ├── Info.plist
│   │       │   ├── Modules/
│   │       │   │   └── module.modulemap
│   │       │   └── PromisesObjC
│   │       ├── leveldb-library.framework/
│   │       │   ├── Headers/
│   │       │   │   ├── c.h
│   │       │   │   ├── cache.h
│   │       │   │   ├── comparator.h
│   │       │   │   ├── db.h
│   │       │   │   ├── dumpfile.h
│   │       │   │   ├── env.h
│   │       │   │   ├── export.h
│   │       │   │   ├── filter_policy.h
│   │       │   │   ├── iterator.h
│   │       │   │   ├── leveldb-library-umbrella.h
│   │       │   │   ├── options.h
│   │       │   │   ├── slice.h
│   │       │   │   ├── status.h
│   │       │   │   ├── table.h
│   │       │   │   ├── table_builder.h
│   │       │   │   └── write_batch.h
│   │       │   ├── Info.plist
│   │       │   ├── Modules/
│   │       │   │   └── module.modulemap
│   │       │   └── leveldb-library
│   │       └── nanopb.framework/
│   │           ├── Headers/
│   │           │   ├── nanopb-umbrella.h
│   │           │   ├── pb.h
│   │           │   ├── pb_common.h
│   │           │   ├── pb_decode.h
│   │           │   └── pb_encode.h
│   │           ├── Info.plist
│   │           ├── Modules/
│   │           │   └── module.modulemap
│   │           └── nanopb
│   ├── GoogleService-Info.plist
│   ├── Keys.plist.example
│   ├── Media.xcassets/
│   │   ├── Accent Color.colorset/
│   │   │   └── Contents.json
│   │   ├── Add Icon/
│   │   │   ├── Add Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add Highlighted.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add Icon.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Add White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Calendar Icon Remove/
│   │   │   ├── Contents.json
│   │   │   ├── Remove Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Remove.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── WhiteRemove.imageset/
│   │   │       └── Contents.json
│   │   ├── Clocker Icon/
│   │   │   ├── ClockerIcon-512.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── Extra Options/
│   │   │   ├── Contents.json
│   │   │   ├── Extra Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Extra.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraHighlighted Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraHighlighted.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── ExtraWhite.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── ExtraWhiteHighlighted.imageset/
│   │   │       └── Contents.json
│   │   ├── Location/
│   │   │   ├── Contents.json
│   │   │   ├── CurrentLocation.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── CurrentLocationDynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── CurrentLocationWhite.imageset/
│   │   │       └── Contents.json
│   │   ├── Menubar Icons/
│   │   │   ├── Contents.json
│   │   │   └── LightModeIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Onboarding/
│   │   │   ├── Contents.json
│   │   │   ├── Dark Menubar.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Dynamic Menubar.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Light Menubar.imageset/
│   │   │       └── Contents.json
│   │   ├── Pin/
│   │   │   ├── Contents.json
│   │   │   ├── Float-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Float.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Pin.imageset/
│   │   │       └── Contents.json
│   │   ├── Power Icon/
│   │   │   ├── Contents.json
│   │   │   ├── Power.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── PowerIcon-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── PowerIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Preferences Toolbar.imageset/
│   │   │   └── Contents.json
│   │   ├── Privacy/
│   │   │   ├── Contents.json
│   │   │   ├── Privacy Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Privacy Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Privacy.imageset/
│   │   │       └── Contents.json
│   │   ├── Settings/
│   │   │   ├── Contents.json
│   │   │   ├── Settings-White.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Settings.imageset/
│   │   │       └── Contents.json
│   │   ├── Sharing/
│   │   │   ├── Contents.json
│   │   │   ├── Sharing Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sharing.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── SharingDarkIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Sunrise/
│   │   │   ├── Contents.json
│   │   │   ├── Sunrise Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunrise.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunset Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Sunset.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── WhiteSunrise.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── WhiteSunset.imageset/
│   │   │       └── Contents.json
│   │   ├── Tabs/
│   │   │   ├── Appearance Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Appearance Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Appearance.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Dark.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Dynamic.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Calendar Tab Icon.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   └── Trash.imageset/
│   │       └── Contents.json
│   ├── Menu Bar/
│   │   ├── MenubarHandler.swift
│   │   ├── StatusContainerView.swift
│   │   ├── StatusItemHandler.swift
│   │   └── StatusItemView.swift
│   ├── Onboarding/
│   │   ├── FinalOnboardingViewController.swift
│   │   ├── Onboarding.storyboard
│   │   ├── OnboardingController.swift
│   │   ├── OnboardingParentViewController.swift
│   │   ├── OnboardingPermissionsViewController.swift
│   │   ├── OnboardingSearchController.swift
│   │   ├── OnboardingWelcomeViewController.swift
│   │   ├── StartAtLoginViewController.swift
│   │   └── WelcomeView.xib
│   ├── Overall App/
│   │   ├── AppDefaults.swift
│   │   ├── AppKit + Additions.swift
│   │   ├── ConfigExport.swift
│   │   ├── DataStore.swift
│   │   ├── DateFormatterManager.swift
│   │   ├── Foundation + Additions.swift
│   │   ├── NetworkManager.swift
│   │   ├── Reach.swift
│   │   ├── String + Additions.swift
│   │   ├── Strings.swift
│   │   ├── Themer.swift
│   │   ├── Timer.swift
│   │   ├── UserDefaults + KVOExtensions.swift
│   │   └── VersionUpdateHandler.swift
│   ├── Panel/
│   │   ├── Data Layer/
│   │   │   └── TimezoneDataOperations.swift
│   │   ├── FloatingWindowController.swift
│   │   ├── Notes Popover/
│   │   │   ├── NotesPopover.swift
│   │   │   ├── NotesPopover.xib
│   │   │   └── TextViewWithPlaceholder.swift
│   │   ├── PanelController.swift
│   │   ├── ParentPanelController+ModernSlider.swift
│   │   ├── ParentPanelController.swift
│   │   ├── Rate Controller/
│   │   │   ├── ReviewController.swift
│   │   │   └── UpcomingEventView.swift
│   │   ├── UI/
│   │   │   ├── AddTableViewCell.swift
│   │   │   ├── BackgroundPanelView.swift
│   │   │   ├── CustomSliderCell.swift
│   │   │   ├── FloatingWindow.xib
│   │   │   ├── HourMarkerViewItem.xib
│   │   │   ├── NoTimezoneView.swift
│   │   │   ├── PanelTableView.swift
│   │   │   ├── Panelr.swift
│   │   │   ├── TimeMarkerViewItem.swift
│   │   │   ├── TimezoneCellView.swift
│   │   │   ├── TimezoneDataSource.swift
│   │   │   └── Toasty.swift
│   │   └── Upcoming Events/
│   │       ├── ParentPanelController+UpcomingEvents.swift
│   │       ├── UpcomingEventViewItem.swift
│   │       ├── UpcomingEventViewItem.xib
│   │       └── UpcomingEventsDataSource.swift
│   ├── Preferences/
│   │   ├── About/
│   │   │   ├── AboutViewController.swift
│   │   │   └── PointingHandCursorButton.swift
│   │   ├── App Feedback/
│   │   │   ├── AppFeedbackWindow.xib
│   │   │   └── AppFeedbackWindowController.swift
│   │   ├── Appearance/
│   │   │   └── AppearanceViewController.swift
│   │   ├── Calendar/
│   │   │   └── CalendarViewController.swift
│   │   ├── General/
│   │   │   ├── PreferencesDataSource.swift
│   │   │   ├── PreferencesViewController.swift
│   │   │   └── SearchDataSource.swift
│   │   ├── Menu Bar/
│   │   │   ├── MenubarTitleProvider.swift
│   │   │   ├── StatusContainerView.swift
│   │   │   ├── StatusItemHandler.swift
│   │   │   ├── StatusItemView.swift
│   │   │   └── UpcomingEventStatusItemView.swift
│   │   ├── OneWindowController.swift
│   │   ├── ParentViewController.swift
│   │   ├── Permissions/
│   │   │   └── PermissionsViewController.swift
│   │   ├── Preferences.storyboard
│   │   └── StartupManager.swift
│   ├── Releases/
│   │   ├── appcast.xml
│   │   └── changelog.md
│   ├── StartupKit/
│   │   ├── .gitignore
│   │   ├── Package.swift
│   │   ├── README.md
│   │   └── Sources/
│   │       └── StartupKit/
│   │           └── StartupManager.swift
│   ├── release.py
│   ├── run
│   └── upload-symbols
├── Readme.md
└── swiftlint-install.sh
Download .txt
SYMBOL INDEX (77 symbols across 31 files)

FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRCommon.h
  function FOUNDATION_STATIC_INLINE (line 34) | FOUNDATION_STATIC_INLINE NSEventModifierFlags SRCarbonToCocoaFlags(UInt3...
  function FOUNDATION_STATIC_INLINE (line 56) | FOUNDATION_STATIC_INLINE UInt32 SRCocoaToCarbonFlags(NSEventModifierFlag...

FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyCodeTransformer.h
  function end (line 113) | end

FILE: Clocker/Clocker/ShortcutRecorder-master/Library/SRRecorderControl.h
  function BOOL (line 420) | BOOL SRShortcutEqualToShortcut(NSDictionary *a, NSDictionary *b)
  function FOUNDATION_STATIC_INLINE (line 433) | FOUNDATION_STATIC_INLINE NSDictionary *SRShortcutWithCocoaModifierFlagsA...

FILE: Clocker/Clocker/ShortcutRecorder-master/Library/ShortcutRecorder.h
  type NSEdgeInsets (line 39) | typedef struct NSEdgeInsets {
  function NS_INLINE (line 46) | NS_INLINE NSEdgeInsets NSEdgeInsetsMake(CGFloat top, CGFloat left, CGFlo...

FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey.h
  function interface (line 15) | interface PTHotKey : NSObject

FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKeyCenter.h
  function interface (line 19) | interface PTHotKeyCenter : NSObject

FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCodeTranslator.h
  function interface (line 11) | interface PTKeyCodeTranslator : NSObject

FILE: Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCombo.h
  function interface (line 11) | interface PTKeyCombo : NSObject <NSCopying>

FILE: Clocker/Frameworks/Firebase/FirebaseDatabase.framework/Headers/FIRDataEventType.h
  type FIRDataEventTypeChildAdded (line 26) | typedef NS_ENUM(NSInteger, FIRDataEventType) {

FILE: Clocker/Frameworks/Firebase/GoogleUtilities.framework/Headers/GULReachabilityChecker.h
  type GULReachabilityStatus (line 23) | typedef enum {

FILE: Clocker/Frameworks/Firebase/PromisesObjC.framework/Headers/FBLPromise+Retry.h
  type id (line 29) | typedef id __nullable (^FBLPromiseRetryWorkBlock)(void)

FILE: Clocker/Frameworks/Firebase/PromisesObjC.framework/Headers/FBLPromiseError.h
  function NS_INLINE (line 33) | NS_INLINE BOOL FBLPromiseErrorIsTimedOut(NSError *error) NS_SWIFT_UNAVAI...
  function NS_INLINE (line 38) | NS_INLINE BOOL FBLPromiseErrorIsValidationFailure(NSError *error) NS_SWI...

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/c.h
  type leveldb_t (line 55) | typedef struct leveldb_t leveldb_t;
  type leveldb_cache_t (line 56) | typedef struct leveldb_cache_t leveldb_cache_t;
  type leveldb_comparator_t (line 57) | typedef struct leveldb_comparator_t leveldb_comparator_t;
  type leveldb_env_t (line 58) | typedef struct leveldb_env_t leveldb_env_t;
  type leveldb_filelock_t (line 59) | typedef struct leveldb_filelock_t leveldb_filelock_t;
  type leveldb_filterpolicy_t (line 60) | typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t;
  type leveldb_iterator_t (line 61) | typedef struct leveldb_iterator_t leveldb_iterator_t;
  type leveldb_logger_t (line 62) | typedef struct leveldb_logger_t leveldb_logger_t;
  type leveldb_options_t (line 63) | typedef struct leveldb_options_t leveldb_options_t;
  type leveldb_randomfile_t (line 64) | typedef struct leveldb_randomfile_t leveldb_randomfile_t;
  type leveldb_readoptions_t (line 65) | typedef struct leveldb_readoptions_t leveldb_readoptions_t;
  type leveldb_seqfile_t (line 66) | typedef struct leveldb_seqfile_t leveldb_seqfile_t;
  type leveldb_snapshot_t (line 67) | typedef struct leveldb_snapshot_t leveldb_snapshot_t;
  type leveldb_writablefile_t (line 68) | typedef struct leveldb_writablefile_t leveldb_writablefile_t;
  type leveldb_writebatch_t (line 69) | typedef struct leveldb_writebatch_t leveldb_writebatch_t;
  type leveldb_writeoptions_t (line 70) | typedef struct leveldb_writeoptions_t leveldb_writeoptions_t;

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/cache.h
  function namespace (line 26) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/comparator.h
  function namespace (line 12) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/db.h
  function namespace (line 15) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/dumpfile.h
  function namespace (line 14) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/env.h
  function namespace (line 46) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/filter_policy.h
  function namespace (line 23) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/iterator.h
  type CleanupNode (line 86) | struct CleanupNode {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/options.h
  function namespace (line 12) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/slice.h
  function namespace (line 26) | namespace leveldb {
  function compare (line 101) | inline int Slice::compare(const Slice& b) const {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/status.h
  function namespace (line 22) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/table.h
  function namespace (line 13) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/table_builder.h
  function namespace (line 22) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/leveldb-library.framework/Headers/write_batch.h
  function namespace (line 29) | namespace leveldb {

FILE: Clocker/Frameworks/Firebase/nanopb.framework/Headers/pb.h
  type uint_least8_t (line 148) | typedef uint_least8_t pb_type_t;
  type pb_size_t (line 212) | typedef uint32_t pb_size_t;
  type pb_ssize_t (line 213) | typedef int32_t pb_ssize_t;
  type uint_least16_t (line 215) | typedef uint_least16_t pb_size_t;
  type int_least16_t (line 216) | typedef int_least16_t pb_ssize_t;
  type uint_least8_t (line 218) | typedef uint_least8_t pb_size_t;
  type int_least8_t (line 219) | typedef int_least8_t pb_ssize_t;
  type uint_least8_t (line 227) | typedef uint_least8_t pb_byte_t;
  type pb_field_s (line 238) | struct pb_field_s
  type pb_field_s (line 239) | struct pb_field_s {
  type pb_bytes_array_s (line 272) | struct pb_bytes_array_s {
  type pb_bytes_array_t (line 276) | typedef struct pb_bytes_array_s pb_bytes_array_t;
  type pb_istream_t (line 296) | typedef struct pb_istream_s pb_istream_t;
  type pb_ostream_t (line 297) | typedef struct pb_ostream_s pb_ostream_t;
  type pb_callback_t (line 298) | typedef struct pb_callback_s pb_callback_t;
  type pb_callback_s (line 299) | struct pb_callback_s {
  type pb_wire_type_t (line 319) | typedef enum {
  type pb_extension_type_t (line 332) | typedef struct pb_extension_type_s pb_extension_type_t;
  type pb_extension_t (line 333) | typedef struct pb_extension_s pb_extension_t;
  type pb_extension_type_s (line 334) | struct pb_extension_type_s {
  type pb_extension_s (line 356) | struct pb_extension_s {

FILE: Clocker/Frameworks/Firebase/nanopb.framework/Headers/pb_common.h
  type pb_field_iter_s (line 15) | struct pb_field_iter_s {
  type pb_field_iter_t (line 23) | typedef struct pb_field_iter_s pb_field_iter_t;

FILE: Clocker/Frameworks/Firebase/nanopb.framework/Headers/pb_decode.h
  type pb_istream_s (line 28) | struct pb_istream_s

FILE: Clocker/Frameworks/Firebase/nanopb.framework/Headers/pb_encode.h
  type pb_ostream_s (line 27) | struct pb_ostream_s

FILE: Clocker/release.py
  function handle_command_execution (line 11) | def handle_command_execution(command, return_value):
  function increment_build_number (line 16) | def increment_build_number():
  function increment_version_to (line 25) | def increment_version_to(new_version):
  function clean_build_analyze_release_config (line 29) | def clean_build_analyze_release_config():
  function test_release_config (line 33) | def test_release_config():
  function main (line 37) | def main():
Condensed preview — 547 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,669K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 63,
    "preview": "# These are supported funding model platforms\n\ngithub: n0shake\n"
  },
  {
    "path": ".gitignore",
    "chars": 293,
    "preview": "\n*.xcuserstate\n.DS_Store\n.DS_Store\nClocker/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishek_banthia.xcuserdatad"
  },
  {
    "path": ".swiftformat",
    "chars": 9,
    "preview": "--disable"
  },
  {
    "path": ".swiftlint.yml",
    "chars": 1583,
    "preview": "disabled_rules: # rule identifiers to exclude from running\n  - type_body_length\n  - file_length\n  - type_name\n  - variab"
  },
  {
    "path": ".travis.yml",
    "chars": 612,
    "preview": "os: osx\nlanguage: swift\nxcode_project: Clocker.xcodeproj # path to your xcodeproj folder\nosx_image: xcode12.2\nbefore_ins"
  },
  {
    "path": "CLAUDE.md",
    "chars": 3639,
    "preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
  },
  {
    "path": "Clocker/AppDelegate.swift",
    "chars": 10305,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport Cocoa\nimport CoreLoggerKit\nimport CoreModelKit\nimport FirebaseCore\nimport F"
  },
  {
    "path": "Clocker/Clocker/Clocker-Info.plist",
    "chars": 2160,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker/Clocker-Prefix.pch",
    "chars": 143,
    "preview": "//\n// Prefix header for all source files of the 'Clocker' target in the 'Clocker' project\n//\n\n#ifdef __OBJC__\n\n#import <"
  },
  {
    "path": "Clocker/Clocker/Clocker.entitlements",
    "chars": 558,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker/LocationController.swift",
    "chars": 4150,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport Cocoa\nimport CoreLocation\nimport CoreLoggerKit\nimport CoreModelKit\n\nprotoco"
  },
  {
    "path": "Clocker/Clocker/MainMenu.xib",
    "chars": 23559,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/.gitignore",
    "chars": 261,
    "preview": "# Xcode\nbuild/*\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!defaul"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/LICENSE.md",
    "chars": 1587,
    "preview": "# ShortcutRecorder\n\nCopyright (c) 2006, Contributors\nAll rights reserved.\n\nRedistribution and use in source and binary f"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/Info.plist",
    "chars": 681,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/Prefix.pch",
    "chars": 82,
    "preview": "\n#ifdef __OBJC__\n    #import <Cocoa/Cocoa.h>\n    #import <Carbon/Carbon.h>\n#endif\n"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRCommon.h",
    "chars": 3406,
    "preview": "//\n//  SRCommon.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  License: BSD"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRCommon.m",
    "chars": 7099,
    "preview": "//\n//  SRCommon.m\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  License: BSD"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyCodeTransformer.h",
    "chars": 4759,
    "preview": "//\n//  SRKeyCodeTransformer.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyCodeTransformer.m",
    "chars": 12287,
    "preview": "//\n//  SRKeyCodeTransformer.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentModifierMaskTransformer.h",
    "chars": 463,
    "preview": "//\n//  SRKeyEquivalentModifierMaskTransformer.h\n//  ShortcutRecorder\n//\n//  Copyright 2012 Contributors. All rights rese"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentModifierMaskTransformer.m",
    "chars": 827,
    "preview": "//\n//  SRKeyEquivalentModifierMaskTransformer.m\n//  ShortcutRecorder\n//\n//  Copyright 2012 Contributors. All rights rese"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentTransformer.h",
    "chars": 427,
    "preview": "//\n//  SRKeyEquivalentTransformer.h\n//  ShortcutRecorder\n//\n//  Copyright 2012 Contributors. All rights reserved.\n//\n// "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRKeyEquivalentTransformer.m",
    "chars": 1096,
    "preview": "//\n//  SRKeyEquivalentTransformer.m\n//  ShortcutRecorder\n//\n//  Copyright 2012 Contributors. All rights reserved.\n//\n// "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRModifierFlagsTransformer.h",
    "chars": 744,
    "preview": "//\n//  SRModifierFlagsTransformer.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n/"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRModifierFlagsTransformer.m",
    "chars": 2481,
    "preview": "//\n//  SRModifierFlagsTransformer.m\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n/"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRRecorderControl.h",
    "chars": 13563,
    "preview": "//\n//  SRRecorderControl.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  Lic"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRRecorderControl.m",
    "chars": 43746,
    "preview": "//\n//  SRRecorderControl.m\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  Lic"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRValidator.h",
    "chars": 4352,
    "preview": "//\n//  SRValidator.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  License: "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/SRValidator.m",
    "chars": 8591,
    "preview": "//\n//  SRValidator.h\n//  ShortcutRecorder\n//\n//  Copyright 2006-2012 Contributors. All rights reserved.\n//\n//  License: "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Library/ShortcutRecorder.h",
    "chars": 1285,
    "preview": "//\n//  ShortcutRecorder.h\n//  ShortcutRecorder\n//  Copyright 2012 Contributors. All rights reserved.\n//\n//  License: BSD"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/Info.plist",
    "chars": 681,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey+ShortcutRecorder.h",
    "chars": 980,
    "preview": "//\n//  PTHotKey+ShortcutRecorder.h\n//  ShortcutRecorder\n//\n//  Created by Ilya Kulakov on 27.02.11.\n//  Copyright 2011 W"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey+ShortcutRecorder.m",
    "chars": 1995,
    "preview": "//\n//  PTHotKey+ShortcutRecorder.m\n//  ShortcutRecorder\n//\n//  Created by Ilya Kulakov on 27.02.11.\n//  Copyright 2011 W"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey.h",
    "chars": 1304,
    "preview": "//\n//  PTHotKey.h\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quentin D."
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKey.m",
    "chars": 2293,
    "preview": "//\n//  PTHotKey.m\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quentin D."
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKeyCenter.h",
    "chars": 909,
    "preview": "//\n//  PTHotKeyCenter.h\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quen"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTHotKeyCenter.m",
    "chars": 7620,
    "preview": "//\n//  PTHotKeyCenter.m\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quen"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCodeTranslator.h",
    "chars": 540,
    "preview": "//\n//  PTKeyCodeTranslator.h\n//  Chercher\n//\n//  Created by Finlay Dobbie on Sat Oct 11 2003.\n//  Copyright (c) 2003 Cli"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCodeTranslator.m",
    "chars": 1880,
    "preview": "//\n//  PTKeyCodeTranslator.m\n//  Chercher\n//\n//  Created by Finlay Dobbie on Sat Oct 11 2003.\n//  Copyright (c) 2003 Cli"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCombo.h",
    "chars": 782,
    "preview": "//\n//  PTKeyCombo.h\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quentin "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/PTHotKey/PTKeyCombo.m",
    "chars": 2444,
    "preview": "//\n//  PTKeyCombo.m\n//  Protein\n//\n//  Created by Quentin Carnicelli on Sat Aug 02 2003.\n//  Copyright (c) 2003 Quentin "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/README.md",
    "chars": 6506,
    "preview": "ShortcutRecorder 2\n====================\n![pre-Yosemite ShortcutRecorder Preview](Demo/example.png)\n![Yosemite ShortcutRe"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/Resources/LICENSE.txt",
    "chars": 2447,
    "preview": "Copyright (c) 2006, contributors to ShortcutRecorder. (See the contributors listed in detail later in the file, or see <"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.podspec",
    "chars": 787,
    "preview": "Pod::Spec.new do |s|\n  s.name = 'ShortcutRecorder'\n  s.homepage = 'https://github.com/Kentzo/ShortcutRecorder'\n  s.summa"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.xcodeproj/project.pbxproj",
    "chars": 83105,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.xcodeproj/xcshareddata/xcschemes/PTHotKey.framework.xcscheme",
    "chars": 2807,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1250\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker/ShortcutRecorder-master/ShortcutRecorder.xcodeproj/xcshareddata/xcschemes/ShortcutRecorder.framework.xcscheme",
    "chars": 2855,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1250\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker/ar.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/ar.lproj/Localizable.strings",
    "chars": 7946,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"كلوكر\";\n\"Th"
  },
  {
    "path": "Clocker/Clocker/ca.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/ca.lproj/Localizable.strings",
    "chars": 7872,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/com.abhishek.ClockerHelper.plist",
    "chars": 401,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker/de.lproj/InfoPlist.strings",
    "chars": 1228,
    "preview": "/* InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16. */\n\"CFBundleDisplayName\" = \"Clocker\";\n\n/* (No "
  },
  {
    "path": "Clocker/Clocker/de.lproj/Localizable.strings",
    "chars": 8706,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"T"
  },
  {
    "path": "Clocker/Clocker/en.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/en.lproj/Localizable.strings",
    "chars": 7984,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/en.lproj/Panel.xib",
    "chars": 70090,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "Clocker/Clocker/es.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/es.lproj/Localizable.strings",
    "chars": 8958,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"T"
  },
  {
    "path": "Clocker/Clocker/fr.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/fr.lproj/Localizable.strings",
    "chars": 8883,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"T"
  },
  {
    "path": "Clocker/Clocker/hi.lproj/InfoPlist.strings",
    "chars": 155,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"विश्व का समय\""
  },
  {
    "path": "Clocker/Clocker/hi.lproj/Localizable.strings",
    "chars": 7767,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"विश्व का सम"
  },
  {
    "path": "Clocker/Clocker/hr.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/hr.lproj/Localizable.strings",
    "chars": 8658,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 7/9/21.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"Th"
  },
  {
    "path": "Clocker/Clocker/it.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/it.lproj/Localizable.strings",
    "chars": 7831,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/ja.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/ja.lproj/Localizable.strings",
    "chars": 7446,
    "preview": "\n\n\"About Tab\" = \"このプログラムについて\";\n\n\n\"Add Button Title\" = \"追加\";\n\n\n\"Appearance Tab\" = \"外観\";\n\n\n\"Back\" = \"戻る\";\n\n/* \n  Localizab"
  },
  {
    "path": "Clocker/Clocker/ko.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/ko.lproj/Localizable.strings",
    "chars": 7138,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"시계\";\n\"Thank"
  },
  {
    "path": "Clocker/Clocker/main.m",
    "chars": 157,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, char *argv[])\n{\n    return NSApplicati"
  },
  {
    "path": "Clocker/Clocker/nl.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/nl.lproj/Localizable.strings",
    "chars": 7872,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/pl.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/pl.lproj/Localizable.strings",
    "chars": 8196,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/pt-BR.lproj/Localizable.strings",
    "chars": 8671,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"T"
  },
  {
    "path": "Clocker/Clocker/pt-PT.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/ru.lproj/InfoPlist.strings",
    "chars": 1140,
    "preview": "/* InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16. */\n\"CFBundleDisplayName\" = \"Clocker\";\n\n/* (No "
  },
  {
    "path": "Clocker/Clocker/ru.lproj/Localizable.strings",
    "chars": 8352,
    "preview": "/* (No Comment) */\n\"CFBundleDisplayName\" = \"Clocker\";\n\"Thank you for helping make Clocker even better!\" = \"Спасибо, что "
  },
  {
    "path": "Clocker/Clocker/tr.lproj/InfoPlist.strings",
    "chars": 144,
    "preview": "/* \n  InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"CF"
  },
  {
    "path": "Clocker/Clocker/tr.lproj/Localizable.strings",
    "chars": 8482,
    "preview": "/* \n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\""
  },
  {
    "path": "Clocker/Clocker/uk.lproj/Localizable.strings",
    "chars": 8074,
    "preview": "/*\n  Localizable.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16.\n\n*/\n\n\"CFBundleDisplayName\" = \"Clocker\";\n\"T"
  },
  {
    "path": "Clocker/Clocker/zh-Hans.lproj/InfoPlist.strings",
    "chars": 1017,
    "preview": "/* InfoPlist.strings\n  Clocker\n\n  Created by Abhishek Banthia on 3/27/16. */\n\"CFBundleDisplayName\" = \"Clocker\";\n\n/* (No "
  },
  {
    "path": "Clocker/Clocker/zh-Hans.lproj/Localizable.strings",
    "chars": 5726,
    "preview": "/* (No Comment) */\n\"CFBundleDisplayName\" = \"解锁器\";\n\"Thank you for helping make Clocker even better!\" = \"感谢您帮助 Clocker 做得更"
  },
  {
    "path": "Clocker/Clocker/zh-Hant.lproj/Localizable.strings",
    "chars": 6502,
    "preview": "\n\n\"About Tab\" = \"關於\";\n\n\n\"Add Button Title\" = \"新增\";\n\n\n\"Appearance Tab\" = \"外觀\";\n\n\n\"Back\" = \"返回\";\n\n/* \n  Localizable.string"
  },
  {
    "path": "Clocker/Clocker-Bridging-Header.h",
    "chars": 248,
    "preview": "//\n//  Clocker-Bridging-Header.h\n//  Clocker\n//\n//  Created by Banthia, Abhishek on 12/22/17.\n//\n\n#import \"iVersion.h\"\n#"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.pbxproj",
    "chars": 144332,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 52;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 198,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:/Users/abhishek"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcshareddata/Clocker.xcscmblueprint",
    "chars": 1638,
    "preview": "{\n  \"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey\" : \"79BC31FA35C73FAE9D63749994DC7D1D9E35A66B\",\n  \"DVTS"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 241,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishek_banthia.xcuserdatad/WorkspaceSettings.xcsettings",
    "chars": 561,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcuserdata/abhishekbanthia.xcuserdatad/IDEFindNavigatorScopes.plist",
    "chars": 182,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/project.xcworkspace/xcuserdata/ban.xcuserdatad/IDEFindNavigatorScopes.plist",
    "chars": 182,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcshareddata/IDETemplateMacros.plist",
    "chars": 264,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcshareddata/xcschemes/Clocker.xcscheme",
    "chars": 5197,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1250\"\n   version = \"1.7\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme",
    "chars": 3635,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1250\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhi.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishek_banthia.xcuserdatad/xcschemes/Clocker.xcscheme",
    "chars": 5566,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0930\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishek_banthia.xcuserdatad/xcschemes/ClockerHelper.xcscheme",
    "chars": 3351,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0930\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishek_banthia.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 976,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 1257,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"26111DB1-8943-459C-82A2-C5091082412F\"\n   type = \"1\"\n   version"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/ClockerHelper.xcscheme",
    "chars": 3687,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1140\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/abhishekbanthia.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 1061,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/ban.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 983,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"F515D608-9FB6-4230-BDAA-714D2FAB3B77\"\n   type = \"1\"\n   version"
  },
  {
    "path": "Clocker/Clocker.xcodeproj/xcuserdata/ban.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 713,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/ClockerHelper/AppDelegate.h",
    "chars": 129,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n#import <Cocoa/Cocoa.h>\n\n@interface AppDelegate : NSObject <NSApplicationDelegate>"
  },
  {
    "path": "Clocker/ClockerHelper/AppDelegate.m",
    "chars": 543,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n#import \"AppDelegate.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDeleg"
  },
  {
    "path": "Clocker/ClockerHelper/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 903,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"16x16\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : "
  },
  {
    "path": "Clocker/ClockerHelper/Base.lproj/Main.storyboard",
    "chars": 56614,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB\" version=\"3.0\" t"
  },
  {
    "path": "Clocker/ClockerHelper/ClockerHelper.entitlements",
    "chars": 240,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/ClockerHelper/Info.plist",
    "chars": 964,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/ClockerHelper/de.lproj/InfoPlist.strings",
    "chars": 53,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerHelper\";\n\n"
  },
  {
    "path": "Clocker/ClockerHelper/de.lproj/Main.strings",
    "chars": 14543,
    "preview": "/* Class = \"NSMenu\"; title = \"Find\"; ObjectID = \"1b7-l0-nxx\"; */\n\"1b7-l0-nxx.title\" = \"Find\";\n\n/* Class = \"NSMenuItem\"; "
  },
  {
    "path": "Clocker/ClockerHelper/main.m",
    "chars": 149,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, const char * argv[]) {\n    return NSAp"
  },
  {
    "path": "Clocker/ClockerHelper/ru.lproj/InfoPlist.strings",
    "chars": 53,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerHelper\";\n\n"
  },
  {
    "path": "Clocker/ClockerHelper/ru.lproj/Main.strings",
    "chars": 14700,
    "preview": "/* Class = \"NSMenu\"; title = \"Find\"; ObjectID = \"1b7-l0-nxx\"; */\n\"1b7-l0-nxx.title\" = \"Найти\";\n\n/* Class = \"NSMenuItem\";"
  },
  {
    "path": "Clocker/ClockerHelper/zh-Hans.lproj/InfoPlist.strings",
    "chars": 53,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerHelper\";\n\n"
  },
  {
    "path": "Clocker/ClockerHelper/zh-Hans.lproj/Main.strings",
    "chars": 14530,
    "preview": "/* Class = \"NSMenu\"; title = \"Find\"; ObjectID = \"1b7-l0-nxx\"; */\n\"1b7-l0-nxx.title\" = \"Find\";\n\n/* Class = \"NSMenuItem\"; "
  },
  {
    "path": "Clocker/ClockerUITests/AboutUsTests.swift",
    "chars": 2279,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass AboutUsTests: XCTestCase {\n    var app: XCUIApplication!\n\n   "
  },
  {
    "path": "Clocker/ClockerUITests/ClockerUITests-Bridging-Header.h",
    "chars": 104,
    "preview": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n"
  },
  {
    "path": "Clocker/ClockerUITests/ClockerUITests.m",
    "chars": 5870,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n#import <XCTest/XCTest.h>\n\n@interface ClockerUITests : XCTestCase\n\n@property (stro"
  },
  {
    "path": "Clocker/ClockerUITests/CopyToClipboardTests.swift",
    "chars": 2425,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass CopyToClipboardTests: XCTestCase {\n    var app: XCUIApplicati"
  },
  {
    "path": "Clocker/ClockerUITests/FloatingWindowTests.swift",
    "chars": 7245,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nextension String {\n    func localizedString() -> String {\n        l"
  },
  {
    "path": "Clocker/ClockerUITests/Info.plist",
    "chars": 701,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/ClockerUITests/NetworkDisconnectionTests.swift",
    "chars": 2250,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass NetworkDisconnectionTests: XCTestCase {\n    var app: XCUIAppl"
  },
  {
    "path": "Clocker/ClockerUITests/OnboardingSearchTests.swift",
    "chars": 3937,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass OnboardingSearchTests: XCTestCase {\n    var app: XCUIApplicat"
  },
  {
    "path": "Clocker/ClockerUITests/OnboardingTests.swift",
    "chars": 6435,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass OnboardingTests: XCTestCase {\n    var app: XCUIApplication!\n "
  },
  {
    "path": "Clocker/ClockerUITests/PanelTests.swift",
    "chars": 4015,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nlet CLUITestingLaunchArgument = \"isUITesting\"\n\nclass PanelTests: XC"
  },
  {
    "path": "Clocker/ClockerUITests/PermissionsTests.swift",
    "chars": 2978,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass PermissionsTests: XCTestCase {\n    var app: XCUIApplication!\n"
  },
  {
    "path": "Clocker/ClockerUITests/PreferencesTest.swift",
    "chars": 17697,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass PreferencesTest: XCTestCase {\n    var app: XCUIApplication!\n\n"
  },
  {
    "path": "Clocker/ClockerUITests/ReviewTests.swift",
    "chars": 1817,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass ReviewTests: XCTestCase {\n    var app: XCUIApplication!\n\n    "
  },
  {
    "path": "Clocker/ClockerUITests/ShortcutTests.swift",
    "chars": 1973,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\nclass ShortcutTests: XCTestCase {\n    var app: XCUIApplication!\n\n  "
  },
  {
    "path": "Clocker/ClockerUITests/de.lproj/InfoPlist.strings",
    "chars": 54,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerUITests\";\n\n"
  },
  {
    "path": "Clocker/ClockerUITests/ru.lproj/InfoPlist.strings",
    "chars": 54,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerUITests\";\n\n"
  },
  {
    "path": "Clocker/ClockerUITests/zh-Hans.lproj/InfoPlist.strings",
    "chars": 54,
    "preview": "/* Bundle name */\n\"CFBundleName\" = \"ClockerUITests\";\n\n"
  },
  {
    "path": "Clocker/ClockerUnitTests/AppDelegateTests.swift",
    "chars": 5874,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport CoreModelKit\nimport XCTest\n\n@testable import Clocker\n\nclass AppDelegateTest"
  },
  {
    "path": "Clocker/ClockerUnitTests/ClockerUnitTests.swift",
    "chars": 21118,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport CoreModelKit\n\n@testable import Clocker\nimport XCTest\n\nclass ClockerUnitTest"
  },
  {
    "path": "Clocker/ClockerUnitTests/DateFormatterManagerTests.swift",
    "chars": 1491,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\n@testable import Clocker\n\nclass DateFormatterManagerTests: XCTestCa"
  },
  {
    "path": "Clocker/ClockerUnitTests/EventInfoTests.swift",
    "chars": 5309,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n@testable import Clocker\nimport EventKit\nimport XCTest\n\nclass EventInfoTests: XCTe"
  },
  {
    "path": "Clocker/ClockerUnitTests/Info.plist",
    "chars": 701,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Clocker/ClockerUnitTests/ReviewControllerTests.swift",
    "chars": 5402,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\n@testable import Clocker\nimport XCTest\n\nclass ReviewControllerTests: XCTestCase {\n"
  },
  {
    "path": "Clocker/ClockerUnitTests/SearchDataSourceTests.swift",
    "chars": 4723,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport CoreModelKit\nimport XCTest\n\n@testable import Clocker\n\nclass SearchDataSourc"
  },
  {
    "path": "Clocker/ClockerUnitTests/StandardMenubarHandlerTests.swift",
    "chars": 11979,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport CoreModelKit\nimport EventKit\nimport XCTest\n\n@testable import Clocker\n\nclass"
  },
  {
    "path": "Clocker/ClockerUnitTests/ThemerTests.swift",
    "chars": 21507,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport XCTest\n\n@testable import Clocker\n\nclass ThemerTests: XCTestCase {\n    priva"
  },
  {
    "path": "Clocker/CoreLoggerKit/.gitignore",
    "chars": 53,
    "preview": ".DS_Store\n/.build\n/Packages\n/*.xcodeproj\nxcuserdata/\n"
  },
  {
    "path": "Clocker/CoreLoggerKit/Package.swift",
    "chars": 630,
    "preview": "// swift-tools-version:5.3\n// The swift-tools-version declares the minimum version of Swift required to build this packa"
  },
  {
    "path": "Clocker/CoreLoggerKit/README.md",
    "chars": 165,
    "preview": "# CoreLoggerKit\n\nEncompasses two main logging classes.\n\n1. Logger: Essentially logs to console\n2. PerfLogger: Uses `sign"
  },
  {
    "path": "Clocker/CoreLoggerKit/Sources/CoreLoggerKit/Logger.swift",
    "chars": 1367,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport Cocoa\nimport os\nimport os.log\nimport os.signpost\n\npublic class Logger: NSOb"
  },
  {
    "path": "Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/CoreLoggerKitTests.swift",
    "chars": 165,
    "preview": "@testable import CoreLoggerKit\nimport XCTest\n\nfinal class CoreLoggerKitTests: XCTestCase {\n    static var allTests = [\n "
  },
  {
    "path": "Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/XCTestManifests.swift",
    "chars": 183,
    "preview": "import XCTest\n\n#if !canImport(ObjectiveC)\n    public func allTests() -> [XCTestCaseEntry] {\n        return [\n           "
  },
  {
    "path": "Clocker/CoreLoggerKit/Tests/LinuxMain.swift",
    "chars": 128,
    "preview": "import XCTest\n\nimport CoreLoggerKitTests\n\nvar tests = [XCTestCaseEntry]()\ntests += CoreLoggerKitTests.allTests()\nXCTMain"
  },
  {
    "path": "Clocker/CoreModelKit/.gitignore",
    "chars": 53,
    "preview": ".DS_Store\n/.build\n/Packages\n/*.xcodeproj\nxcuserdata/\n"
  },
  {
    "path": "Clocker/CoreModelKit/Package.swift",
    "chars": 1187,
    "preview": "// swift-tools-version:5.3\n// The swift-tools-version declares the minimum version of Swift required to build this packa"
  },
  {
    "path": "Clocker/CoreModelKit/README.md",
    "chars": 47,
    "preview": "# CoreModelKit\n\nA description of this package.\n"
  },
  {
    "path": "Clocker/CoreModelKit/Sources/CoreModelKit/SearchResults.swift",
    "chars": 1931,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport Cocoa\n\npublic enum ResultStatus {\n    public static let okay = \"OK\"\n    pub"
  },
  {
    "path": "Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift",
    "chars": 12483,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport Cocoa\nimport CoreLoggerKit\n\nstruct ModelConstants {\n    static let customLa"
  },
  {
    "path": "Clocker/CoreModelKit/Tests/CoreModelKitTests/TimezoneDataEqualityTests.swift",
    "chars": 2231,
    "preview": "// Copyright © 2015 Abhishek Banthia\n\nimport CoreModelKit\nimport Foundation\nimport XCTest\n\nclass TimezoneDataEqualityTes"
  },
  {
    "path": "Clocker/CoreModelKit/Tests/CoreModelKitTests/XCTestManifests.swift",
    "chars": 182,
    "preview": "import XCTest\n\n#if !canImport(ObjectiveC)\n    public func allTests() -> [XCTestCaseEntry] {\n        return [\n           "
  },
  {
    "path": "Clocker/CoreModelKit/Tests/LinuxMain.swift",
    "chars": 126,
    "preview": "import XCTest\n\nimport CoreModelKitTests\n\nvar tests = [XCTestCaseEntry]()\ntests += CoreModelKitTests.allTests()\nXCTMain(t"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Constants.swift",
    "chars": 1132,
    "preview": "//\n//  Constants.swift\n//  DateTools\n//\n//  Created by Grayson Webster on 8/17/16.\n//  Copyright © 2016 Grayson Webster."
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Bundle.swift",
    "chars": 407,
    "preview": "//\n//  Date+Bundle.swift\n//  DateTools\n//\n//  Created by Matthew York on 8/26/16.\n//  Copyright © 2016 Matthew York. All"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Comparators.swift",
    "chars": 21818,
    "preview": "//\n//  Date+Comparators.swift\n//  DateToolsTests\n//\n//  Created by Matthew York on 8/26/16.\n//  Copyright © 2016 Matthew"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Components.swift",
    "chars": 9412,
    "preview": "//\n//  Date+Components.swift\n//  DateToolsTests\n//\n//  Created by Matthew York on 8/26/16.\n//  Copyright © 2016 Matthew "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Format.swift",
    "chars": 5973,
    "preview": "//\n//  Date+Format.swift\n//  DateToolsTests\n//\n//  Created by Matthew York on 8/23/16.\n//  Copyright © 2016 Matthew York"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Inits.swift",
    "chars": 1226,
    "preview": "//\n//  Date+DateTools.swift\n//  DateTools\n//\n//  Created by Grayson Webster on 8/17/16.\n//  Copyright © 2016 Grayson Web"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+Manipulations.swift",
    "chars": 5930,
    "preview": "//\n//  Date+Manipulations.swift\n//  DateToolsTests\n//\n//  Created by Grayson Webster on 9/28/16.\n//  Copyright © 2016 Ma"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/Date+TimeAgo.swift",
    "chars": 9643,
    "preview": "//\n//  Date+TimeAgo.swift\n//  DateToolsTests\n//\n//  Created by Matthew York on 8/23/16.\n//  Copyright © 2016 Matthew Yor"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/am.lproj/DateTools.strings",
    "chars": 2048,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d ቀናት በፊት\";\n\n/* No comment provided by engineer. */\n\"%d hours a"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/bg.lproj/DateTools.strings",
    "chars": 1742,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"преди %d дена\";\n\n/* No comment provided by engineer. */\n\"%d hour"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/ca.lproj/DateTools.strings",
    "chars": 1695,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"Fa %d dies\";\n\n/* No comment provided by engineer. */\n\"%d hours a"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/cs.lproj/DateTools.strings",
    "chars": 1893,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"Před %d dny\";\n\n/* No comment provided by engineer. */\n\"%d hours "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/cy.lproj/DateTools.strings",
    "chars": 1715,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d diwrnod yn ôl\";\n\n/* No comment provided by engineer. */\n\"%d h"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/da.lproj/DateTools.strings",
    "chars": 1737,
    "preview": "/* No comment provided by engineer. */\n \"%d days ago\" = \"%d dage siden\";\n \n /* No comment provided by engineer. */\n \"%d "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/de.lproj/DateTools.strings",
    "chars": 1935,
    "preview": "/* No comment provided by engineer. */\n \"%d days ago\" = \"Vor %d Tagen\";\n \n /* No comment provided by engineer. */\n \"%d h"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/en.lproj/DateTools.strings",
    "chars": 2310,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d days ago\";\n\n/* No comment provided by engineer. */\n\"%d hours "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/es.lproj/DateTools.strings",
    "chars": 1968,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"Hace %d días\";\n\n/* No comment provided by engineer. */\n\"%d hours"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/eu.lproj/DateTools.strings",
    "chars": 1810,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"Orain dela %d egun\";\n\n/* No comment provided by engineer. */\n\"%d"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/fi.lproj/DateTools.strings",
    "chars": 1759,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d päivää sitten\";\n\n/* No comment provided by engineer. */\n\"%d h"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/fr.lproj/DateTools.strings",
    "chars": 1985,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"Il y a %d jours\";\n\n/* No comment provided by engineer. */\n\"%d ho"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/gu.lproj/DateTools.strings",
    "chars": 2108,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d દિવસ પહેલા\";\n\n/* No comment provided by engineer. */\n\"%d hour"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/he.lproj/DateTools.strings",
    "chars": 1643,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"לפני %d ימים\";\n\n/* No comment provided by engineer. */\n\"%d hours"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/hi.lproj/DateTools.strings",
    "chars": 2065,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d दिन पहले\";\n\n/* No comment provided by engineer. */\n\"%d hours "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/hr.lproj/DateTools.strings",
    "chars": 1123,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dana\";\n\n/* No comment provided by engineer. */\n\"%d hours ago\""
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/hu.lproj/DateTools.strings",
    "chars": 1662,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d napja\";\n\n/* No comment provided by engineer. */\n\"%d hours ago"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/id.lproj/DateTools.strings",
    "chars": 1752,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d hari yang lalu\";\n\n/* No comment provided by engineer. */\n\"%d "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/is.lproj/DateTools.strings",
    "chars": 1739,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dögum síðan\";\n\n/* No comment provided by engineer. */\n\"%d hou"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/it.lproj/DateTools.strings",
    "chars": 1705,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d giorni fa\";\n\n/* No comment provided by engineer. */\n\"%d hours"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/ja.lproj/DateTools.strings",
    "chars": 1888,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d日前\";\n\n/* No comment provided by engineer. */\n\"%d hours ago\" = "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/ko.lproj/DateTools.strings",
    "chars": 1533,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d일 전\";\n\n/* No comment provided by engineer. */\n\"%d hours ago\" ="
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/lv.lproj/DateTools.strings",
    "chars": 756,
    "preview": "\"1 year ago\" = \"Pirms gada\";\n\"1 month ago\" = \"Pirms mēneša\";\n\"1 week ago\" = \"Pirms nedēļas\";\n\"1 day ago\" = \"Pirms dienas"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/ms.lproj/DateTools.strings",
    "chars": 2160,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d hari yang lepas\";\n\n/* No comment provided by engineer. */\n\"%d"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/nb.lproj/DateTools.strings",
    "chars": 2676,
    "preview": "/*\n RULES:\n Assume value for (seconds, hours, minutes, days, weeks, months or years) is XXXY, Y is last digit, XY is las"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/nl.lproj/DateTools.strings",
    "chars": 1735,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dagen geleden\";\n\n/* No comment provided by engineer. */\n\"%d h"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/pl.lproj/DateTools.strings",
    "chars": 1754,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dni temu\";\n\n/* No comment provided by engineer. */\n\"%d hours "
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/pt-PT.lproj/DateTools.strings",
    "chars": 1714,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dias atrás\";\n\n/* No comment provided by engineer. */\n\"%d hour"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/pt.lproj/DateTools.strings",
    "chars": 1700,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"%d dias atrás\";\n\n/* No comment provided by engineer. */\n\"%d hour"
  },
  {
    "path": "Clocker/Dependencies/Date Additions/DateTools.bundle/ro.lproj/DateTools.strings",
    "chars": 2050,
    "preview": "/* No comment provided by engineer. */\n\"%d days ago\" = \"În urmă cu %d zile\";\n\n/* No comment provided by engineer. */\n\"%d"
  }
]

// ... and 347 more files (download for full content)

About this extraction

This page contains the full source code of the n0shake/Clocker GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 547 files (2.4 MB), approximately 651.8k tokens, and a symbol index with 77 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!