Browse Source

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

pull/113/head
Abhishek 3 years ago
parent
commit
f23e3f54d2
  1. 28
      Clocker/AppDelegate.swift
  2. 34
      Clocker/ClockerUnitTests/ClockerUnitTests.swift
  3. 2
      Clocker/Events and Reminders/EventCenter.swift
  4. 2
      Clocker/Onboarding/OnboardingParentViewController.swift
  5. 80
      Clocker/Onboarding/OnboardingSearchController.swift
  6. 63
      Clocker/Overall App/AppDefaults.swift
  7. 5
      Clocker/Overall App/ConfigExport.swift
  8. 32
      Clocker/Overall App/DataStore.swift
  9. 4
      Clocker/Overall App/String + Additions.swift
  10. 35
      Clocker/Panel/Data Layer/TimezoneDataOperations.swift
  11. 2
      Clocker/Panel/PanelController.swift
  12. 29
      Clocker/Panel/ParentPanelController.swift
  13. 3
      Clocker/Panel/Rate Controller/UpcomingEventView.swift
  14. 23
      Clocker/Panel/UI/TimezoneDataSource.swift
  15. 3
      Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift
  16. 4
      Clocker/Preferences/Appearance/AppearanceViewController.swift
  17. 10
      Clocker/Preferences/General/PreferencesDataSource.swift
  18. 6
      Clocker/Preferences/General/PreferencesViewController.swift
  19. 2
      Clocker/Preferences/Menu Bar/MenubarTitleProvider.swift
  20. 10
      Clocker/Preferences/Menu Bar/StatusContainerView.swift
  21. 9
      Clocker/Preferences/Menu Bar/StatusItemHandler.swift
  22. 2
      Clocker/Preferences/Menu Bar/StatusItemView.swift
  23. 20
      Clocker/Preferences/Preferences.storyboard

28
Clocker/AppDelegate.swift

@ -43,7 +43,7 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
// Required for migrating our model type to CoreModelKit
NSKeyedUnarchiver.setClass(CoreModelKit.TimezoneData.classForKeyedUnarchiver(), forClassName: "Clocker.TimezoneData")
AppDefaults.initialize()
AppDefaults.initialize(with: DataStore.shared(), defaults: UserDefaults.standard)
// Check if we can show the onboarding flow!
showOnboardingFlowIfEligible()
@ -73,9 +73,9 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
}
@objc private func openPreferencesWindow() {
let displayMode = UserDefaults.standard.integer(forKey: CLShowAppInForeground)
let displayMode = DataStore.shared().shouldDisplay(.showAppInForeground)
if displayMode == 1 {
if displayMode {
let floatingWindow = FloatingWindowController.shared()
floatingWindow.openPreferences(NSButton())
} else {
@ -88,16 +88,22 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
NSApp.setActivationPolicy(.accessory)
}
private lazy var controller: OnboardingController? = {
let onboardingStoryboard = NSStoryboard(name: NSStoryboard.Name("Onboarding"), bundle: nil)
return onboardingStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("onboardingFlow")) as? OnboardingController
}()
private var controller: OnboardingController?
private func showOnboardingFlowIfEligible() {
let shouldLaunchOnboarding = (DataStore.shared().retrieve(key: CLShowOnboardingFlow) == nil && DataStore.shared().timezones().isEmpty)
|| ProcessInfo.processInfo.arguments.contains(CLOnboaringTestsLaunchArgument)
shouldLaunchOnboarding ? controller?.launch() : continueUsually()
let isTestInProgress = ProcessInfo.processInfo.arguments.contains(CLOnboaringTestsLaunchArgument)
let shouldLaunchOnboarding =
(DataStore.shared().retrieve(key: CLShowOnboardingFlow) == 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() {

34
Clocker/ClockerUnitTests/ClockerUnitTests.swift

@ -53,23 +53,23 @@ class ClockerUnitTests: XCTestCase {
"longitude": "-95.9345034"]
private var operations: TimezoneDataOperations {
return TimezoneDataOperations(with: TimezoneData(with: mumbai))
return TimezoneDataOperations(with: TimezoneData(with: mumbai), store: DataStore.shared())
}
private var californiaOperations: TimezoneDataOperations {
return TimezoneDataOperations(with: TimezoneData(with: california))
return TimezoneDataOperations(with: TimezoneData(with: california), store: DataStore.shared())
}
private var floridaOperations: TimezoneDataOperations {
return TimezoneDataOperations(with: TimezoneData(with: florida))
return TimezoneDataOperations(with: TimezoneData(with: florida), store: DataStore.shared())
}
private var aucklandOperations: TimezoneDataOperations {
return TimezoneDataOperations(with: TimezoneData(with: auckland))
return TimezoneDataOperations(with: TimezoneData(with: auckland), store: DataStore.shared())
}
private var omahaOperations: TimezoneDataOperations {
return TimezoneDataOperations(with: TimezoneData(with: omaha))
return TimezoneDataOperations(with: TimezoneData(with: omaha), store: DataStore.shared())
}
func testOverridingSecondsComponent_shouldHideSeconds() {
@ -81,7 +81,7 @@ class ClockerUnitTests: XCTestCase {
TimezoneData(with: california)]
timezoneObjects.forEach {
let operationsObject = TimezoneDataOperations(with: $0)
let operationsObject = TimezoneDataOperations(with: $0, store: DataStore.shared())
let currentTime = operationsObject.time(with: 0)
XCTAssert(currentTime.count == 8) // 8 includes 2 colons
@ -97,7 +97,7 @@ class ClockerUnitTests: XCTestCase {
let currentFavourites = DataStore.shared().timezones()
let oldCount = currentFavourites.count
let operationsObject = TimezoneDataOperations(with: timezoneData)
let operationsObject = TimezoneDataOperations(with: timezoneData, store: DataStore.shared())
operationsObject.saveObject()
let newDefaults = DataStore.shared().timezones()
@ -151,7 +151,7 @@ class ClockerUnitTests: XCTestCase {
// California is absent. Add it!
if filteredCount.count == 0 {
let timezoneData = TimezoneData(with: california)
let operationsObject = TimezoneDataOperations(with: timezoneData)
let operationsObject = TimezoneDataOperations(with: timezoneData, store: DataStore.shared())
operationsObject.saveObject()
}
@ -179,7 +179,7 @@ class ClockerUnitTests: XCTestCase {
func testSunriseSunset() {
let dataObject = TimezoneData(with: mumbai)
let operations = TimezoneDataOperations(with: dataObject)
let operations = TimezoneDataOperations(with: dataObject, store: DataStore.shared())
XCTAssertNotNil(operations.formattedSunriseTime(with: 0))
XCTAssertNotNil(dataObject.sunriseTime)
@ -187,7 +187,7 @@ class ClockerUnitTests: XCTestCase {
let timezoneObject = TimezoneData(with: onlyTimezone)
timezoneObject.selectionType = .timezone
let timezoneOperations = TimezoneDataOperations(with: timezoneObject)
let timezoneOperations = TimezoneDataOperations(with: timezoneObject, store: DataStore.shared())
XCTAssertTrue(timezoneOperations.formattedSunriseTime(with: 0) == "")
XCTAssertNil(timezoneObject.sunriseTime)
@ -196,7 +196,7 @@ class ClockerUnitTests: XCTestCase {
func testDateWithSliderValue() {
let dataObject = TimezoneData(with: mumbai)
let operations = TimezoneDataOperations(with: dataObject)
let operations = TimezoneDataOperations(with: dataObject, store: DataStore.shared())
XCTAssertNotNil(operations.date(with: 0, displayType: .menu))
}
@ -359,7 +359,7 @@ class ClockerUnitTests: XCTestCase {
func testWithAllLocales() {
let dataObject1 = TimezoneData(with: mumbai)
let operations = TimezoneDataOperations(with: dataObject1)
let operations = TimezoneDataOperations(with: dataObject1, store: DataStore.shared())
for locale in Locale.availableIdentifiers {
let currentLocale = Locale(identifier: locale)
@ -430,4 +430,14 @@ class ClockerUnitTests: XCTestCase {
XCTAssertEqual(subject.subviews.count, 2) // Two textfields
XCTAssertEqual(subject.subviews.first?.layer?.animationKeys(), ["notimezone.emoji"])
}
func testDefaultsWiping() {
let defaultsDict: [String: Any] = ["test1": "testString", "test2": 24]
let domainName = "com.test.clocker"
let defaults = UserDefaults(suiteName: domainName)
defaults?.setPersistentDomain(defaultsDict, forName: domainName)
defaults?.wipe(for: domainName)
XCTAssertNil(defaults?.object(forKey: "test1"))
XCTAssertNil(defaults?.object(forKey: "test2"))
}
}

2
Clocker/Events and Reminders/EventCenter.swift

@ -42,7 +42,7 @@ class EventCenter: NSObject {
}
private func refetchAll() {
Logger.info("\nRefetching events from the store")
Logger.info("Refetching events from the store")
eventsForDate = [:]
filteredEvents = [:]

2
Clocker/Onboarding/OnboardingParentViewController.swift

@ -189,7 +189,7 @@ class OnboardingParentViewController: NSViewController {
currentTimezone.isSystemTimezone = true
currentTimezone.placeID = "Home"
let operations = TimezoneDataOperations(with: currentTimezone)
let operations = TimezoneDataOperations(with: currentTimezone, store: DataStore.shared())
operations.saveObject(at: 0)
}

80
Clocker/Onboarding/OnboardingSearchController.swift

@ -21,7 +21,7 @@ class OnboardingSearchController: NSViewController {
@IBOutlet private var accessoryLabel: NSTextField!
@IBOutlet var undoButton: NSButton!
private var searchResultsDataSource: SearchDataSource!
private var searchResultsDataSource: SearchDataSource?
private var dataTask: URLSessionDataTask? = .none
private var themeDidChangeNotification: NSObjectProtocol?
@ -81,17 +81,19 @@ class OnboardingSearchController: NSViewController {
@objc func doubleClickAction(_ tableView: NSTableView) {
[accessoryLabel].forEach { $0?.isHidden = false }
if tableView.selectedRow >= 0, tableView.selectedRow < searchResultsDataSource.resultsCount() {
let selectedType = searchResultsDataSource.placeForRow(resultsTableView.selectedRow)
if tableView.selectedRow >= 0, tableView.selectedRow < (searchResultsDataSource?.resultsCount() ?? 0) {
let selectedType = searchResultsDataSource?.placeForRow(resultsTableView.selectedRow)
switch selectedType {
case .city:
if let filteredGoogleResult = searchResultsDataSource.retrieveFilteredResultFromGoogleAPI(resultsTableView.selectedRow) {
if let filteredGoogleResult = searchResultsDataSource?.retrieveFilteredResultFromGoogleAPI(resultsTableView.selectedRow) {
addTimezoneToDefaults(filteredGoogleResult)
}
return
case .timezone:
cleanupAfterInstallingTimezone()
return
case .none:
return
}
}
}
@ -100,28 +102,28 @@ class OnboardingSearchController: NSViewController {
let data = TimezoneData()
data.setLabel(CLEmptyString)
let currentSelection = searchResultsDataSource.retrieveSelectedTimezone(resultsTableView.selectedRow)
let metaInfo = metadata(for: currentSelection)
data.timezoneID = metaInfo.0.name
data.formattedAddress = metaInfo.1.formattedName
data.selectionType = .timezone
data.isSystemTimezone = metaInfo.0.name == NSTimeZone.system.identifier
if let currentSelection = searchResultsDataSource?.retrieveSelectedTimezone(resultsTableView.selectedRow) {
let metaInfo = metadata(for: currentSelection)
data.timezoneID = metaInfo.0.name
data.formattedAddress = metaInfo.1.formattedName
data.selectionType = .timezone
data.isSystemTimezone = metaInfo.0.name == NSTimeZone.system.identifier
let operationObject = TimezoneDataOperations(with: data)
operationObject.saveObject()
let operationObject = TimezoneDataOperations(with: data, store: DataStore.shared())
operationObject.saveObject()
searchResultsDataSource.cleanupFilterArray()
searchResultsDataSource.timezoneFilteredArray = []
searchResultsDataSource.calculateChangesets()
searchBar.stringValue = CLEmptyString
searchResultsDataSource?.cleanupFilterArray()
searchResultsDataSource?.timezoneFilteredArray = []
searchResultsDataSource?.calculateChangesets()
searchBar.stringValue = CLEmptyString
accessoryLabel.stringValue = "Added \(metaInfo.1.formattedName)."
undoButton.isHidden = false
setupLabelHidingTimer()
accessoryLabel.stringValue = "Added \(metaInfo.1.formattedName)."
undoButton.isHidden = false
setupLabelHidingTimer()
resultsTableView.reloadData()
resultsTableView.isHidden = true
resultsTableView.reloadData()
resultsTableView.isHidden = true
}
}
private func metadata(for selection: TimezoneMetadata) -> (NSTimeZone, TimezoneMetadata) {
@ -194,7 +196,7 @@ class OnboardingSearchController: NSViewController {
private func fetchTimezone(for latitude: Double, and longitude: Double, _ dataObject: TimezoneData) {
if NetworkManager.isConnected() == false || ProcessInfo.processInfo.arguments.contains("mockTimezoneDown") {
setInfoLabel(PreferencesConstants.noInternetConnectivityError)
searchResultsDataSource.cleanupFilterArray()
searchResultsDataSource?.cleanupFilterArray()
resultsTableView.reloadData()
return
}
@ -215,7 +217,7 @@ class OnboardingSearchController: NSViewController {
}
if error == nil, let json = response, let response = json.decodeTimezone() {
if self.resultsTableView.selectedRow >= 0, self.resultsTableView.selectedRow < self.searchResultsDataSource.resultsCount() {
if self.resultsTableView.selectedRow >= 0, self.resultsTableView.selectedRow < (self.searchResultsDataSource?.resultsCount()) ?? 0 {
var filteredAddress = "Error"
if let address = dataObject.formattedAddress {
@ -312,7 +314,7 @@ class OnboardingSearchController: NSViewController {
@objc func actualSearch() {
func setupForError() {
searchResultsDataSource.calculateChangesets()
searchResultsDataSource?.calculateChangesets()
resultsTableView.isHidden = true
}
@ -345,12 +347,12 @@ class OnboardingSearchController: NSViewController {
return
}
self.searchResultsDataSource.cleanupFilterArray()
self.searchResultsDataSource.timezoneFilteredArray = []
self.searchResultsDataSource?.cleanupFilterArray()
self.searchResultsDataSource?.timezoneFilteredArray = []
if let errorPresent = error {
self.findLocalSearchResultsForTimezones()
if self.searchResultsDataSource.timezoneFilteredArray.count == 0 {
if self.searchResultsDataSource?.timezoneFilteredArray.count == 0 {
self.presentErrorMessage(errorPresent.localizedDescription)
setupForError()
return
@ -391,12 +393,12 @@ class OnboardingSearchController: NSViewController {
private func findLocalSearchResultsForTimezones() {
let lowercasedSearchString = searchBar.stringValue.lowercased()
searchResultsDataSource.searchTimezones(lowercasedSearchString)
searchResultsDataSource?.searchTimezones(lowercasedSearchString)
}
private func prepareUIForPresentingResults() {
setInfoLabel(CLEmptyString)
if searchResultsDataSource.calculateChangesets() {
if let dataSource = searchResultsDataSource, dataSource.calculateChangesets() {
resultsTableView.isHidden = false
resultsTableView.reloadData()
}
@ -421,13 +423,13 @@ class OnboardingSearchController: NSViewController {
return TimezoneData(with: totalPackage)
}
searchResultsDataSource.setFilteredArrayValue(finalTimezones)
searchResultsDataSource?.setFilteredArrayValue(finalTimezones)
}
private func resetSearchView() {
searchResultsDataSource.cleanupFilterArray()
searchResultsDataSource.timezoneFilteredArray = []
searchResultsDataSource.calculateChangesets()
searchResultsDataSource?.cleanupFilterArray()
searchResultsDataSource?.timezoneFilteredArray = []
searchResultsDataSource?.calculateChangesets()
resultsTableView.reloadData()
searchBar.stringValue = CLEmptyString
searchBar.placeholderString = "Press Enter to Search"
@ -441,15 +443,15 @@ class OnboardingSearchController: NSViewController {
extension OnboardingSearchController: NSTableViewDataSource {
func numberOfRows(in _: NSTableView) -> Int {
return searchResultsDataSource != nil ? searchResultsDataSource.resultsCount() : 0
return searchResultsDataSource?.resultsCount() ?? 0
}
func tableView(_ tableView: NSTableView, viewFor _: NSTableColumn?, row: Int) -> NSView? {
if let result = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "resultCellView"), owner: self) as? ResultTableViewCell,
row >= 0,
row < searchResultsDataSource.resultsCount()
row < (searchResultsDataSource?.resultsCount() ?? 0)
{
let currentSelection = searchResultsDataSource.retrieveResult(row)
let currentSelection = searchResultsDataSource?.retrieveResult(row)
if let timezone = currentSelection as? TimezoneMetadata {
result.result.stringValue = " \(timezone.formattedName)"
} else if let location = currentSelection as? TimezoneData {
@ -466,7 +468,7 @@ extension OnboardingSearchController: NSTableViewDataSource {
extension OnboardingSearchController: NSTableViewDelegate {
func tableView(_: NSTableView, heightOfRow row: Int) -> CGFloat {
if row == 0, searchResultsDataSource.resultsCount() == 0 {
if row == 0, searchResultsDataSource?.resultsCount() == 0 {
return 30
}
@ -474,7 +476,7 @@ extension OnboardingSearchController: NSTableViewDelegate {
}
func tableView(_: NSTableView, shouldSelectRow row: Int) -> Bool {
return searchResultsDataSource.resultsCount() == 0 ? row != 0 : true
return searchResultsDataSource?.resultsCount() == 0 ? row != 0 : true
}
func tableView(_: NSTableView, rowViewForRow _: Int) -> NSTableRowView? {

63
Clocker/Overall App/AppDefaults.swift

@ -4,46 +4,19 @@ import Cocoa
import CoreLoggerKit
class AppDefaults {
class func initialize() {
initializeDefaults()
class func initialize(with store: DataStore, defaults: UserDefaults) {
initializeDefaults(with: store, defaults: defaults)
}
private class func deleteOldUserDefaults() {
let userDefaults = UserDefaults.standard
// Now delete the old preferences
if let bundleID = Bundle.main.bundleIdentifier, userDefaults.object(forKey: "PreferencesHaveBeenWiped") == nil {
userDefaults.removePersistentDomain(forName: bundleID)
userDefaults.set(true, forKey: "PreferencesHaveBeenWiped")
}
}
private class func initializeDefaults() {
let userDefaults = UserDefaults.standard
let dataStore = DataStore.shared()
let timezones = dataStore.timezones()
let selectedCalendars = userDefaults.object(forKey: CLSelectedCalendars)
// Now delete the old preferences
userDefaults.wipeIfNeccesary()
private class func initializeDefaults(with store: DataStore, defaults: UserDefaults) {
let timezones = store.timezones()
let selectedCalendars = defaults.object(forKey: CLSelectedCalendars)
// Register the usual suspects
userDefaults.register(defaults: defaultsDictionary())
dataStore.setTimezones(timezones)
userDefaults.set(selectedCalendars, forKey: CLSelectedCalendars)
// Set the theme default as Light!
setDefaultTheme()
}
private class func setDefaultTheme() {
let defaults = UserDefaults.standard
defaults.register(defaults: defaultsDictionary())
if defaults.object(forKey: CLThemeKey) == nil {
Themer.shared().set(theme: 0)
}
store.setTimezones(timezones)
defaults.set(selectedCalendars, forKey: CLSelectedCalendars)
}
private class func defaultsDictionary() -> [String: Any] {
@ -69,25 +42,9 @@ class AppDefaults {
}
}
extension String {
func localized() -> String {
return NSLocalizedString(self, comment: "Title for \(self)")
}
}
extension UserDefaults {
// Use this with caution. Exposing this for debugging purposes only.
func wipe() {
if let bundleID = Bundle.main.bundleIdentifier {
removePersistentDomain(forName: bundleID)
}
}
func wipeIfNeccesary() {
if let bundleID = Bundle.main.bundleIdentifier, object(forKey: "PreferencesHaveBeenWiped") == nil {
Logger.info("Wiping all user defaults")
removePersistentDomain(forName: bundleID)
set(true, forKey: "PreferencesHaveBeenWiped")
}
func wipe(for bundleID: String) {
removePersistentDomain(forName: bundleID)
}
}

5
Clocker/Overall App/ConfigExport.swift

@ -1,6 +1,7 @@
// Copyright © 2015 Abhishek Banthia
import CoreModelKit
import CoreLoggerKit
import Foundation
struct ConfigExport {
@ -34,7 +35,7 @@ struct ConfigExport {
var clockerPrefs: [String: Any] = [:]
for (key, value) in dictionaryRep {
if selectedKeys.contains(key) {
print("Key is \(key) and value is \(value)")
Logger.info("Config Export: Key is \(key) and value is \(value)")
clockerPrefs[key] = value
}
}
@ -73,7 +74,7 @@ struct ConfigExport {
let json = try JSONSerialization.data(withJSONObject: clockerPrefs, options: .prettyPrinted)
print(json)
} catch {
print("Failure Observed \(error.localizedDescription)")
Logger.info("Failure Observed \(error.localizedDescription)")
}
}
}

32
Clocker/Overall App/DataStore.swift

@ -41,8 +41,6 @@ class DataStore: NSObject {
init(with defaults: UserDefaults) {
super.init()
userDefaults = defaults
shouldDisplayDayInMenubar = shouldDisplay(.dayInMenubar)
shouldDisplayDateInMenubar = shouldDisplay(.dateInMenubar)
setupSyncNotification()
}
@ -66,7 +64,7 @@ class DataStore: NSObject {
@objc func ubiquitousKeyValueStoreChanged(_ notification: Notification) {
let userInfo = notification.userInfo ?? [:]
let ubiquitousStore = notification.object as? NSUbiquitousKeyValueStore
print("--- User Info is \(userInfo)")
Logger.info("Ubiquitous Store Changed: User Info is \(userInfo)")
let currentTimezones = userDefaults.object(forKey: CLDefaultPreferenceKey) as? [Data]
let cloudTimezones = ubiquitousStore?.object(forKey: CLDefaultPreferenceKey) as? [Data]
let cloudLastUpdateDate = (ubiquitousStore?.object(forKey: CLUbiquitousStoreLastUpdateKey) as? Date) ?? Date()
@ -113,20 +111,14 @@ class DataStore: NSObject {
}
}
func updateDayPreference() {
shouldDisplayDayInMenubar = shouldDisplay(.dayInMenubar)
}
func updateDateInPreference() {
shouldDisplayDateInMenubar = shouldDisplay(.dateInMenubar)
// MARK: Date (May 8th) in Compact Menubar
func shouldShowDateInMenubar() -> Bool {
return shouldDisplay(.dateInMenubar)
}
// MARK: Day (Sun, Mon etc.) in Compact Menubar
func shouldShowDayInMenubar() -> Bool {
return shouldDisplayDayInMenubar
}
func shouldShowDateInMenubar() -> Bool {
return shouldDisplayDateInMenubar
return shouldDisplay(.dayInMenubar)
}
func retrieve(key: String) -> Any? {
@ -189,11 +181,11 @@ class DataStore: NSObject {
}
return value.isEqual(to: NSNumber(value: 1))
case .dateInMenubar:
return shouldDisplayHelper(CLShowDateInMenu)
return shouldDisplayNonObjectHelper(CLShowDateInMenu)
case .placeInMenubar:
return shouldDisplayHelper(CLShowPlaceInMenu)
case .dayInMenubar:
return shouldDisplayHelper(CLShowDayInMenu)
return shouldDisplayNonObjectHelper(CLShowDayInMenu)
case .appDisplayOptions:
return shouldDisplayHelper(CLAppDisplayOptions)
case .menubarCompactMode:
@ -215,6 +207,12 @@ class DataStore: NSObject {
}
return value.isEqual(to: NSNumber(value: 0))
}
// MARK: Some values are stored as plain integers; objectForKey: will return nil, so using integerForKey:
private func shouldDisplayNonObjectHelper(_ key: String) -> Bool {
let value = userDefaults.integer(forKey: key)
return value == 0
}
}
extension DataStore {

4
Clocker/Overall App/String + Additions.swift

@ -14,4 +14,8 @@ extension String {
return filteredAddress
}
func localized() -> String {
return NSLocalizedString(self, comment: "Title for \(self)")
}
}

35
Clocker/Panel/Data Layer/TimezoneDataOperations.swift

@ -6,14 +6,17 @@ import CoreLoggerKit
import CoreModelKit
class TimezoneDataOperations: NSObject {
private var dataObject: TimezoneData!
private let dataObject: TimezoneData
private let store: DataStore
private lazy var nsCalendar = Calendar.autoupdatingCurrent
private static var gregorianCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)
private static var swiftyCalendar = Calendar(identifier: .gregorian)
private static let currentLocale = Locale.current.identifier
init(with timezone: TimezoneData) {
init(with timezone: TimezoneData, store: DataStore) {
dataObject = timezone
self.store = store
super.init()
}
}
@ -28,7 +31,7 @@ extension TimezoneDataOperations {
return CLEmptyString
}
if dataObject.timezoneFormat(DataStore.shared().timezoneFormat()) == DateFormat.epochTime {
if dataObject.timezoneFormat(store.timezoneFormat()) == DateFormat.epochTime {
let timezone = TimeZone(identifier: dataObject.timezone())
let offset = timezone?.secondsFromGMT(for: newDate) ?? 0
let value = Int(Date().timeIntervalSince1970 + Double(offset))
@ -36,7 +39,7 @@ extension TimezoneDataOperations {
}
let dateFormatter = DateFormatterManager.dateFormatterWithFormat(with: .none,
format: dataObject.timezoneFormat(DataStore.shared().timezoneFormat()),
format: dataObject.timezoneFormat(store.timezoneFormat()),
timezoneIdentifier: dataObject.timezone(),
locale: Locale.autoupdatingCurrent)
@ -80,15 +83,15 @@ extension TimezoneDataOperations {
func compactMenuTitle() -> String {
var subtitle = CLEmptyString
let shouldDayBeShown = DataStore.shared().shouldShowDayInMenubar()
let shouldLabelBeShownAlongWithTime = !DataStore.shared().shouldDisplay(.placeInMenubar)
let shouldDayBeShown = store.shouldShowDayInMenubar()
let shouldLabelBeShownAlongWithTime = !store.shouldDisplay(.placeInMenubar)
if shouldDayBeShown, shouldLabelBeShownAlongWithTime {
let substring = date(with: 0, displayType: .menu)
subtitle.append(substring)
}
let shouldDateBeShown = DataStore.shared().shouldShowDateInMenubar()
let shouldDateBeShown = store.shouldShowDateInMenubar()
if shouldDateBeShown, shouldLabelBeShownAlongWithTime {
let date = Date().formatter(with: "MMM d", timeZone: dataObject.timezone())
subtitle.isEmpty ? subtitle.append("\(date)") : subtitle.append(" \(date)")
@ -100,15 +103,15 @@ extension TimezoneDataOperations {
func compactMenuSubtitle() -> String {
var subtitle = CLEmptyString
let shouldDayBeShown = DataStore.shared().shouldShowDayInMenubar()
let shouldLabelsNotBeShownAlongWithTime = DataStore.shared().shouldDisplay(.placeInMenubar)
let shouldDayBeShown = store.shouldShowDayInMenubar()
let shouldLabelsNotBeShownAlongWithTime = store.shouldDisplay(.placeInMenubar)
if shouldDayBeShown, shouldLabelsNotBeShownAlongWithTime {
let substring = date(with: 0, displayType: .menu)
subtitle.append(substring)
}
let shouldDateBeShown = DataStore.shared().shouldShowDateInMenubar()
let shouldDateBeShown = store.shouldShowDateInMenubar()
if shouldDateBeShown, shouldLabelsNotBeShownAlongWithTime {
let date = Date().formatter(with: "MMM d", timeZone: dataObject.timezone())
subtitle.isEmpty ? subtitle.append("\(date)") : subtitle.append(" \(date)")
@ -122,7 +125,7 @@ extension TimezoneDataOperations {
func menuTitle() -> String {
var menuTitle = CLEmptyString
let dataStore = DataStore.shared()
let dataStore = store
let shouldCityBeShown = dataStore.shouldDisplay(.placeInMenubar)
let shouldDayBeShown = dataStore.shouldShowDayInMenubar()
@ -199,7 +202,7 @@ extension TimezoneDataOperations {
}
func date(with sliderValue: Int, displayType: TimezoneData.DateDisplayType) -> String {
guard let relativeDayPreference = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber else {
guard let relativeDayPreference = store.retrieve(key: CLRelativeDateKey) as? NSNumber else {
assertionFailure("Data was unexpectedly nil")
return CLEmptyString
}
@ -332,7 +335,7 @@ extension TimezoneDataOperations {
let minuteDifference = calculateTimeDifference(with: local as NSDate, timezoneDate: timezoneDate as NSDate)
minuteDifference == 0 ? replaceAgo.append("behind") : replaceAgo.append("\(minuteDifference) mins behind")
minuteDifference == 0 ? replaceAgo.append("behind") : replaceAgo.append("\(minuteDifference)m behind")
return replaceAgo.lowercased()
}
@ -388,7 +391,7 @@ extension TimezoneDataOperations {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.timeZone = TimeZone(identifier: dataObject.timezone())
dateFormatter.dateFormat = dataObject.timezoneFormat(DataStore.shared().timezoneFormat())
dateFormatter.dateFormat = dataObject.timezoneFormat(store.timezoneFormat())
return dateFormatter.string(from: correct)
}
@ -417,10 +420,10 @@ extension TimezoneDataOperations {
}
func saveObject(at index: Int = -1) {
var defaults = DataStore.shared().timezones()
var defaults = store.timezones()
let encodedObject = NSKeyedArchiver.archivedData(withRootObject: dataObject as Any)
index == -1 ? defaults.append(encodedObject) : defaults.insert(encodedObject, at: index)
DataStore.shared().setTimezones(defaults)
store.setTimezones(defaults)
}
}

2
Clocker/Panel/PanelController.swift

@ -268,7 +268,7 @@ class PanelController: ParentPanelController {
if count >= 1 || DataStore.shared().shouldDisplay(.showMeetingInMenubar) {
if let delegate = NSApplication.shared.delegate as? AppDelegate {
Logger.info("\nWe will be invalidating the menubar timer as we want the parent timer to take care of both panel and menubar ")
Logger.info("We will be invalidating the menubar timer as we want the parent timer to take care of both panel and menubar ")
delegate.invalidateMenubarTimer(false)
}

29
Clocker/Panel/ParentPanelController.swift

@ -89,7 +89,7 @@ class ParentPanelController: NSWindowController {
// Upcoming Events
@IBOutlet var upcomingEventCollectionView: NSCollectionView!
@IBOutlet var upcomingEventContainerView: NSView!
public var upcomingEventsDataSource: UpcomingEventsDataSource!
public var upcomingEventsDataSource: UpcomingEventsDataSource?
var defaultPreferences: [Data] {
return DataStore.shared().timezones()
@ -426,7 +426,7 @@ class ParentPanelController: NSWindowController {
if let note = object?.note, note.isEmpty == false {
newHeight += 20
} else if let obj = object,
TimezoneDataOperations(with: obj).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) != nil
TimezoneDataOperations(with: obj, store: DataStore.shared()).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) != nil
{
newHeight += 20
}
@ -436,7 +436,7 @@ class ParentPanelController: NSWindowController {
// Set it to 90 expicity in case the row height is calculated be higher.
newHeight = 88.0
if let note = object?.note, note.isEmpty, let obj = object, TimezoneDataOperations(with: obj).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) == nil {
if let note = object?.note, note.isEmpty, let obj = object, TimezoneDataOperations(with: obj, store: DataStore.shared()).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) == nil {
newHeight -= 20.0
}
}
@ -509,12 +509,13 @@ class ParentPanelController: NSWindowController {
updatePanelColor()
let defaults = DataStore.shared().timezones()
let store = DataStore.shared()
let defaults = store.timezones()
let convertedTimezones = defaults.map { data -> TimezoneData in
TimezoneData.customObject(from: data)!
}
datasource = TimezoneDataSource(items: convertedTimezones)
datasource = TimezoneDataSource(items: convertedTimezones, store: store)
mainTableView.dataSource = datasource
mainTableView.delegate = datasource
mainTableView.panelDelegate = datasource
@ -585,6 +586,9 @@ class ParentPanelController: NSWindowController {
}
private lazy var menubarTitleHandler = MenubarTitleProvider(with: DataStore.shared(), eventStore: EventCenter.sharedCenter())
static private let attributes: [NSAttributedString.Key : Any] = [NSAttributedString.Key.font: NSFont.monospacedDigitSystemFont(ofSize: 13.0, weight: NSFont.Weight.regular),
NSAttributedString.Key.baselineOffset : 0.1]
@objc func updateTime() {
let store = DataStore.shared()
@ -596,7 +600,8 @@ class ParentPanelController: NSWindowController {
if store.shouldDisplay(.menubarCompactMode) {
status.updateCompactMenubar()
} else {
status.statusItem.title = menubarTitleHandler.titleForMenubar()
status.statusItem.button?.attributedTitle = NSAttributedString(string: menubarTitleHandler.titleForMenubar() ?? "",
attributes: ParentPanelController.attributes)
}
}
}
@ -623,7 +628,7 @@ class ParentPanelController: NSWindowController {
if modernContainerView != nil, modernSlider.isHidden == false, modernContainerView.currentlyInFocus {
return
}
let dataOperation = TimezoneDataOperations(with: model)
let dataOperation = TimezoneDataOperations(with: model, store: DataStore.shared())
cellView.time.stringValue = dataOperation.time(with: futureSliderValue)
cellView.sunriseSetTime.stringValue = dataOperation.formattedSunriseTime(with: futureSliderValue)
cellView.sunriseSetTime.lineBreakMode = .byClipping
@ -635,7 +640,7 @@ class ParentPanelController: NSWindowController {
}
if let note = model.note, !note.isEmpty {
cellView.noteLabel.stringValue = note
} else if let value = TimezoneDataOperations(with: model).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) {
} else if let value = TimezoneDataOperations(with: model, store: DataStore.shared()).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) {
cellView.noteLabel.stringValue = value
} else {
cellView.noteLabel.stringValue = CLEmptyString
@ -829,7 +834,7 @@ class ParentPanelController: NSWindowController {
if self.upcomingEventCollectionView != nil,
let upcomingEvents = eventCenter.upcomingEventsForDay(events)
{
self.upcomingEventsDataSource.updateEventsDataSource(upcomingEvents)
self.upcomingEventsDataSource?.updateEventsDataSource(upcomingEvents)
self.upcomingEventCollectionView.reloadData()
return
}
@ -840,7 +845,7 @@ class ParentPanelController: NSWindowController {
}
} else {
if upcomingEventCollectionView != nil {
upcomingEventsDataSource.updateEventsDataSource([])
upcomingEventsDataSource?.updateEventsDataSource([])
upcomingEventCollectionView.reloadData()
return
}
@ -1124,7 +1129,7 @@ extension ParentPanelController: NSSharingServicePickerDelegate {
return clipboardCopy
}
let timezoneOperations = TimezoneDataOperations(with: earliestTimezone)
let timezoneOperations = TimezoneDataOperations(with: earliestTimezone, store: DataStore.shared())
var sectionTitle = timezoneOperations.todaysDate(with: 0) // TODO: Take slider value into consideration
clipboardCopy.append("\(sectionTitle)\n")
@ -1132,7 +1137,7 @@ extension ParentPanelController: NSSharingServicePickerDelegate {
if $0 < sortedByTime.count,
let dataModel = TimezoneData.customObject(from: sortedByTime[$0])
{
let dataOperations = TimezoneDataOperations(with: dataModel)
let dataOperations = TimezoneDataOperations(with: dataModel, store: DataStore.shared())
let date = dataOperations.todaysDate(with: 0)
let time = dataOperations.time(with: 0)
if date != sectionTitle {

3
Clocker/Panel/Rate Controller/UpcomingEventView.swift

@ -1,6 +1,7 @@
// Copyright © 2015 Abhishek Banthia
import Cocoa
import CoreLoggerKit
class ModernSliderContainerView: NSView {
private var trackingArea: NSTrackingArea?
@ -67,7 +68,7 @@ class DraggableClipView: NSClipView {
clickPoint = nil
gestureInProgress = false
default:
print("Default case is happening \(event.type)")
Logger.info("Default mouse event occurred for \(event.type)")
}
}
}

23
Clocker/Panel/UI/TimezoneDataSource.swift

@ -6,10 +6,13 @@ import CoreModelKit
class TimezoneDataSource: NSObject {
var timezones: [TimezoneData] = []
var sliderValue: Int = 0
var dataStore: DataStore
init(items: [TimezoneData]) {
init(items: [TimezoneData], store: DataStore) {
sliderValue = 0
timezones = Array(items)
dataStore = store
super.init()
}
}
@ -51,7 +54,7 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
}
let currentModel = timezones[row]
let operation = TimezoneDataOperations(with: currentModel)
let operation = TimezoneDataOperations(with: currentModel, store: dataStore)
cellView.sunriseSetTime.stringValue = operation.formattedSunriseTime(with: sliderValue)
cellView.sunriseImage.image = currentModel.isSunriseOrSunset ? Themer.shared().sunriseImage() : Themer.shared().sunsetImage()
@ -85,12 +88,12 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
return 100
}
if let userFontSize = DataStore.shared().retrieve(key: CLUserFontSizePreference) as? NSNumber,
if let userFontSize = dataStore.retrieve(key: CLUserFontSizePreference) as? NSNumber,
timezones.count > row,
let relativeDisplay = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber
let relativeDisplay = dataStore.retrieve(key: CLRelativeDateKey) as? NSNumber
{
let model = timezones[row]
let shouldShowSunrise = DataStore.shared().shouldDisplay(.sunrise)
let shouldShowSunrise = dataStore.shouldDisplay(.sunrise)
var rowHeight: Int = userFontSize == 4 ? 60 : 65
@ -104,7 +107,7 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
if let note = model.note, !note.isEmpty {
rowHeight += userFontSize.intValue + 15
} else if TimezoneDataOperations(with: model).nextDaylightSavingsTransitionIfAvailable(with: sliderValue) != nil {
} else if TimezoneDataOperations(with: model, store: dataStore).nextDaylightSavingsTransitionIfAvailable(with: sliderValue) != nil {
rowHeight += userFontSize.intValue + 15
}
@ -140,7 +143,7 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
tableView.removeRows(at: indexSet, withAnimation: NSTableView.AnimationOptions())
if DataStore.shared().shouldDisplay(ViewType.showAppInForeground) {
if self.dataStore.shouldDisplay(ViewType.showAppInForeground) {
windowController.deleteTimezone(at: row)
} else {
guard let panelController = PanelController.panel() else { return }
@ -173,12 +176,14 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
let response = alert.runModal()
if response.rawValue == 1000 {
OperationQueue.main.addOperation {
OperationQueue.main.addOperation { [weak self] in
guard let sSelf = self else { return }
let indexSet = IndexSet(integer: row)
tableView.removeRows(at: indexSet, withAnimation: NSTableView.AnimationOptions.slideUp)
if DataStore.shared().shouldDisplay(ViewType.showAppInForeground) {
if sSelf.dataStore.shouldDisplay(ViewType.showAppInForeground) {
let windowController = FloatingWindowController.shared()
windowController.deleteTimezone(at: row)
} else {

3
Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift

@ -18,7 +18,6 @@ extension NSNib.Name {
}
enum AppFeedbackConstants {
static let CLAppFeedbackNibIdentifier = "AppFeedbackWindow"
static let CLAppFeedbackNoResponseString = "Not Provided"
static let CLAppFeedbackNameProperty = "name"
static let CLAppFeedbackEmailProperty = "email"
@ -256,7 +255,7 @@ class AppFeedbackWindowController: NSWindowController {
isActivityInProgress = false
let alert = NSAlert()
alert.messageText = "Thank you for helping make Clocker even better!"
alert.messageText = AppFeedbackConstants.CLFeedbackAlertTitle
alert.informativeText = AppFeedbackConstants.CLFeedbackAlertInformativeText
alert.addButton(withTitle: AppFeedbackConstants.CLFeedbackAlertButtonTitle)
alert.beginSheetModal(for: feedbackWindow) { _ in

4
Clocker/Preferences/Appearance/AppearanceViewController.swift

@ -316,12 +316,10 @@ class AppearanceViewController: ParentViewController {
}
@IBAction func displayDayInMenubarAction(_: Any) {
DataStore.shared().updateDayPreference()
updateStatusItem()
}
@IBAction func displayDateInMenubarAction(_: Any) {
DataStore.shared().updateDateInPreference()
updateStatusItem()
}
@ -381,7 +379,7 @@ extension AppearanceViewController: NSTableViewDataSource, NSTableViewDelegate {
}
let currentModel = previewTimezones[row]
let operation = TimezoneDataOperations(with: currentModel)
let operation = TimezoneDataOperations(with: currentModel, store: DataStore.shared())
cellView.sunriseSetTime.stringValue = operation.formattedSunriseTime(with: 0)
cellView.sunriseImage.image = currentModel.isSunriseOrSunset ? Themer.shared().sunriseImage() : Themer.shared().sunsetImage()

10
Clocker/Preferences/General/PreferencesDataSource.swift

@ -22,11 +22,13 @@ protocol PreferenceSelectionUpdates: AnyObject {
class PreferencesDataSource: NSObject {
private weak var updateDelegate: PreferenceSelectionUpdates?
private let store: DataStore
var selectedTimezones: [Data] {
return DataStore.shared().timezones()
return store.timezones()
}
init(callbackDelegate delegate: PreferenceSelectionUpdates) {
init(with store: DataStore, callbackDelegate delegate: PreferenceSelectionUpdates) {
self.store = store
updateDelegate = delegate
super.init()
}
@ -75,7 +77,7 @@ extension PreferencesDataSource: NSTableViewDelegate {
newOrder.insert(currentObject, at: destination)
DataStore.shared().setTimezones(newOrder)
store.setTimezones(newOrder)
tableView.reloadData()
@ -185,7 +187,7 @@ extension PreferencesDataSource: NSTableViewDataSource {
let encodedObject = NSKeyedArchiver.archivedData(withRootObject: timezone)
var newDefaults = selectedTimezones
newDefaults[index] = encodedObject
DataStore.shared().setTimezones(newDefaults)
store.setTimezones(newDefaults)
}
private func updateMenubarTitles() {

6
Clocker/Preferences/General/PreferencesViewController.swift

@ -116,7 +116,7 @@ class PreferencesViewController: ParentViewController {
searchField.placeholderString = "Enter city, state, country or timezone name"
selectionsDataSource = PreferencesDataSource(callbackDelegate: self)
selectionsDataSource = PreferencesDataSource(with: DataStore.shared(), callbackDelegate: self)
timezoneTableView.dataSource = selectionsDataSource
timezoneTableView.delegate = selectionsDataSource
@ -612,7 +612,7 @@ extension PreferencesViewController {
// Mark if the timezone is same as local timezone
let timezoneObject = TimezoneData(with: newTimeZone)
let operationsObject = TimezoneDataOperations(with: timezoneObject)
let operationsObject = TimezoneDataOperations(with: timezoneObject, store: DataStore.shared())
operationsObject.saveObject()
Logger.log(object: ["PlaceName": filteredAddress, "Timezone": timezone.timeZoneId], for: "Filtered Address")
@ -746,7 +746,7 @@ extension PreferencesViewController {
data.selectionType = .timezone
data.isSystemTimezone = metaInfo.0.name == NSTimeZone.system.identifier
let operationObject = TimezoneDataOperations(with: data)
let operationObject = TimezoneDataOperations(with: data, store: DataStore.shared())
operationObject.saveObject()
searchResultsDataSource.cleanupFilterArray()

2
Clocker/Preferences/Menu Bar/MenubarTitleProvider.swift

@ -34,7 +34,7 @@ class MenubarTitleProvider: NSObject {
if menubarTitles.isEmpty == false {
let titles = menubarTitles.map { data -> String? in
let timezone = TimezoneData.customObject(from: data)
let operationsObject = TimezoneDataOperations(with: timezone!)
let operationsObject = TimezoneDataOperations(with: timezone!, store: store)
return "\(operationsObject.menuTitle().trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines))"
}

10
Clocker/Preferences/Menu Bar/StatusContainerView.swift

@ -47,6 +47,12 @@ protocol StatusItemViewConforming {
func statusItemViewIdentifier() -> String
}
/// Observe for User Default changes for timezones in App Delegate and reconstruct the Status View if neccesary
/// We'll inject the menubar timezones into Status Container View which'll pass it to StatusItemView
/// The benefit of doing so is reducing time-spent calculating menubar timezones and deserialization through `TimezoneData.customObject`
/// Also inject, `shouldDisplaySecondsInMenubar`
///
class StatusContainerView: NSView {
private var previousX: Int = 0
private let store: DataStore
@ -96,7 +102,7 @@ class StatusContainerView: NSView {
if let timezoneObject = TimezoneData.customObject(from: timezone) {
let precalculatedWidth = Double(compactWidth(for: timezoneObject, with: store))
let operationObject = TimezoneDataOperations(with: timezoneObject)
let operationObject = TimezoneDataOperations(with: timezoneObject, store: store)
let calculatedSubtitleSize = compactModeTimeFont.size(for: operationObject.compactMenuSubtitle(),
width: precalculatedWidth,
attributes: timeBasedAttributes)
@ -158,7 +164,7 @@ class StatusContainerView: NSView {
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
]
let operation = TimezoneDataOperations(with: timezone)
let operation = TimezoneDataOperations(with: timezone, store: store)
let bestSize = compactModeTimeFont.size(for: operation.compactMenuSubtitle(),
width: Double(compactWidth(for: timezone, with: store)),
attributes: timeBasedAttributes)

9
Clocker/Preferences/Menu Bar/StatusItemHandler.swift

@ -61,7 +61,7 @@ class StatusItemHandler: NSObject {
setClockerIcon()
}
Logger.info("\nStatus Bar Current State changed: \(currentState)\n")
Logger.info("Status Bar Current State changed: \(currentState)\n")
}
}
@ -365,9 +365,10 @@ class StatusItemHandler: NSObject {
setClockerIcon()
return
}
statusItem.button?.title = menubarText
statusItem.button?.font = NSFont.monospacedDigitSystemFont(ofSize: 14.0, weight: NSFont.Weight.regular)
let attributes = [NSAttributedString.Key.font: NSFont.monospacedDigitSystemFont(ofSize: 13.0, weight: NSFont.Weight.regular),
NSAttributedString.Key.baselineOffset : 0.1] as [NSAttributedString.Key : Any]
statusItem.button?.attributedTitle = NSAttributedString(string: menubarText, attributes: attributes)
statusItem.button?.image = nil
statusItem.button?.imagePosition = .imageLeft
}

2
Clocker/Preferences/Menu Bar/StatusItemView.swift

@ -40,7 +40,7 @@ class StatusItemView: NSView {
private let locationView = NSTextField(labelWithString: "Hello")
private let timeView = NSTextField(labelWithString: "Mon 19:14 PM")
private var operationsObject: TimezoneDataOperations {
return TimezoneDataOperations(with: dataObject)
return TimezoneDataOperations(with: dataObject, store: DataStore.shared())
}
private var timeAttributes: [NSAttributedString.Key: AnyObject] {

20
Clocker/Preferences/Preferences.storyboard

@ -283,7 +283,7 @@
<rect key="frame" x="8" y="13" width="317" height="45"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="nKQ-6v-Ka2">
<font key="font" size="11" name="Avenir-Book"/>
<string key="title">When selected, your upcoming meeting title will appear in the menubar 30 mins before it starts. All Day Events won't be shown in the menubar!</string>
<string key="title">When selected, your upcoming meeting title will appear in the menubar 30m before it starts. All Day Events won't be shown in the menubar!</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -411,7 +411,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="sourceCellView" misplaced="YES" id="yOO-gI-yD1" customClass="SourceTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="11" y="1" width="270" height="33"/>
<rect key="frame" x="1" y="1" width="270" height="33"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="AIA-oD-PWu">
@ -434,7 +434,7 @@
</connections>
</tableCellView>
<tableCellView identifier="calendarCellView" misplaced="YES" id="Guw-Ai-ICX" customClass="CalendarTableViewCell" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="11" y="36" width="270" height="33"/>
<rect key="frame" x="1" y="36" width="270" height="33"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4c9-Nn-Umd">
@ -984,7 +984,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="111" rowSizeStyle="automatic" viewBased="YES" id="KbJ-p4-i6E">
<rect key="frame" x="0.0" y="0.0" width="412" height="113"/>
<rect key="frame" x="0.0" y="0.0" width="412" height="98"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
@ -1513,7 +1513,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<searchField toolTip="Search a timezone" wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Dha-h9-Nd0">
<rect key="frame" x="8" y="121" width="320" height="23"/>
<rect key="frame" x="8" y="97" width="320" height="23"/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Enter a city, state, country name" usesSingleLineMode="YES" maximumRecents="5" id="ikU-Tm-0WZ">
<font key="font" size="13" name="Avenir-Light"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -1570,13 +1570,13 @@ DQ
</connections>
</button>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="32" horizontalPageScroll="10" verticalLineScroll="32" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0wY-ff-FLW">
<rect key="frame" x="8" y="30" width="320" height="81"/>
<rect key="frame" x="8" y="30" width="320" height="57"/>
<clipView key="contentView" drawsBackground="NO" id="rGc-3M-cCq">
<rect key="frame" x="0.0" y="0.0" width="320" height="81"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" rowHeight="30" rowSizeStyle="automatic" viewBased="YES" id="xkl-2X-ZCb">
<rect key="frame" x="0.0" y="0.0" width="320" height="81"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -1666,14 +1666,14 @@ DQ
</scroller>
</scrollView>
<progressIndicator wantsLayer="YES" focusRingType="none" horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="100" displayedWhenStopped="NO" bezeled="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="0A5-gp-lay">
<rect key="frame" x="160" y="90" width="16" height="16"/>
<rect key="frame" x="160" y="78" width="16" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="fgE-77-Vda"/>
<constraint firstAttribute="width" constant="16" id="pwe-em-e0a"/>
</constraints>
</progressIndicator>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xgb-wU-8RU">
<rect key="frame" x="18" y="60" width="300" height="22"/>
<rect key="frame" x="18" y="48" width="300" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="zqt-d8-yas"/>
</constraints>

Loading…
Cancel
Save