Browse Source

Tests and formatting.

pull/113/head
Abhishek 3 years ago
parent
commit
642303d138
  1. 2
      Clocker/AppDelegate.swift
  2. 4
      Clocker/Clocker.xcodeproj/project.pbxproj
  3. 68
      Clocker/ClockerUnitTests/AppDelegateTests.swift
  4. 15
      Clocker/ClockerUnitTests/ClockerUnitTests.swift
  5. 6
      Clocker/ClockerUnitTests/DateFormatterManagerTests.swift
  6. 75
      Clocker/ClockerUnitTests/ReviewControllerTests.swift
  7. 139
      Clocker/ClockerUnitTests/SearchDataSourceTests.swift
  8. 20
      Clocker/ClockerUnitTests/ThemerTests.swift
  9. 6
      Clocker/CoreLoggerKit/Package.swift
  10. 2
      Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/CoreLoggerKitTests.swift
  11. 2
      Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/XCTestManifests.swift
  12. 8
      Clocker/CoreModelKit/Package.swift
  13. 2
      Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift
  14. 2
      Clocker/CoreModelKit/Tests/CoreModelKitTests/XCTestManifests.swift
  15. 6
      Clocker/Events and Reminders/CalendarHandler.swift
  16. 3
      Clocker/Events and Reminders/RemindersHandler.swift
  17. 10
      Clocker/Menu Bar/StatusContainerView.swift
  18. 3
      Clocker/Menu Bar/StatusItemHandler.swift
  19. 8
      Clocker/Menu Bar/StatusItemView.swift
  20. 7
      Clocker/Onboarding/OnboardingSearchController.swift
  21. 4
      Clocker/Overall App/ConfigExport.swift
  22. 1
      Clocker/Overall App/DateFormatterManager.swift
  23. 3
      Clocker/Overall App/Themer.swift
  24. 2
      Clocker/Panel/Data Layer/TimezoneDataOperations.swift
  25. 10
      Clocker/Panel/Notes Popover/NotesPopover.swift
  26. 2
      Clocker/Panel/Notes Popover/TextViewWithPlaceholder.swift
  27. 5
      Clocker/Panel/PanelController.swift
  28. 35
      Clocker/Panel/ParentPanelController.swift
  29. 2
      Clocker/Panel/UI/PanelTableView.swift
  30. 6
      Clocker/Panel/UI/TimezoneCellView.swift
  31. 3
      Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift
  32. 2
      Clocker/Preferences/About/PointingHandCursorButton.swift
  33. 5
      Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift
  34. 5
      Clocker/Preferences/Appearance/AppearanceViewController.swift
  35. 8
      Clocker/Preferences/Calendar/CalendarViewController.swift
  36. 7
      Clocker/Preferences/General/PreferencesDataSource.swift
  37. 14
      Clocker/Preferences/General/PreferencesViewController.swift
  38. 42
      Clocker/Preferences/General/SearchDataSource.swift
  39. 21
      Clocker/Preferences/Menu Bar/StatusContainerView.swift
  40. 7
      Clocker/Preferences/Menu Bar/StatusItemHandler.swift
  41. 8
      Clocker/Preferences/Menu Bar/StatusItemView.swift
  42. 8
      Clocker/Preferences/Menu Bar/UpcomingEventStatusItemView.swift
  43. 6
      Clocker/StartupKit/Package.swift

2
Clocker/AppDelegate.swift

@ -261,7 +261,7 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
open func invalidateMenubarTimer(_ showIcon: Bool) { open func invalidateMenubarTimer(_ showIcon: Bool) {
statusBarHandler.invalidateTimer(showIcon: showIcon, isSyncing: true) statusBarHandler.invalidateTimer(showIcon: showIcon, isSyncing: true)
} }
private func setupPanelObserverIfNeeeded() { private func setupPanelObserverIfNeeeded() {
if panelObserver == nil { if panelObserver == nil {
panelObserver = panelController.observe(\.hasActivePanel, options: [.new]) { obj, _ in panelObserver = panelController.observe(\.hasActivePanel, options: [.new]) { obj, _ in

4
Clocker/Clocker.xcodeproj/project.pbxproj

@ -53,6 +53,7 @@
35584D1427EF8EB5006E3EAD /* ThemerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1327EF8EB5006E3EAD /* ThemerTests.swift */; }; 35584D1427EF8EB5006E3EAD /* ThemerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1327EF8EB5006E3EAD /* ThemerTests.swift */; };
35584D1827F0B019006E3EAD /* DateFormatterManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */; }; 35584D1827F0B019006E3EAD /* DateFormatterManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */; };
35584D1A27F0B64E006E3EAD /* AppDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */; }; 35584D1A27F0B64E006E3EAD /* AppDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */; };
35621CFC27F66C1900926D5C /* SearchDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35621CFB27F66C1900926D5C /* SearchDataSourceTests.swift */; };
357391872507277500D30819 /* TimeMarkerViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357391852507277500D30819 /* TimeMarkerViewItem.swift */; }; 357391872507277500D30819 /* TimeMarkerViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357391852507277500D30819 /* TimeMarkerViewItem.swift */; };
357391882507277500D30819 /* HourMarkerViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 357391862507277500D30819 /* HourMarkerViewItem.xib */; }; 357391882507277500D30819 /* HourMarkerViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 357391862507277500D30819 /* HourMarkerViewItem.xib */; };
3579765E2680208C009DDA6E /* ParentPanelController+ModernSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3579765D2680208C009DDA6E /* ParentPanelController+ModernSlider.swift */; }; 3579765E2680208C009DDA6E /* ParentPanelController+ModernSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3579765D2680208C009DDA6E /* ParentPanelController+ModernSlider.swift */; };
@ -291,6 +292,7 @@
35584D1327EF8EB5006E3EAD /* ThemerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemerTests.swift; sourceTree = "<group>"; }; 35584D1327EF8EB5006E3EAD /* ThemerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemerTests.swift; sourceTree = "<group>"; };
35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatterManagerTests.swift; sourceTree = "<group>"; }; 35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatterManagerTests.swift; sourceTree = "<group>"; };
35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegateTests.swift; sourceTree = "<group>"; }; 35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegateTests.swift; sourceTree = "<group>"; };
35621CFB27F66C1900926D5C /* SearchDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchDataSourceTests.swift; sourceTree = "<group>"; };
3569A44E25441F320087E254 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; }; 3569A44E25441F320087E254 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
357391852507277500D30819 /* TimeMarkerViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeMarkerViewItem.swift; sourceTree = "<group>"; }; 357391852507277500D30819 /* TimeMarkerViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeMarkerViewItem.swift; sourceTree = "<group>"; };
357391862507277500D30819 /* HourMarkerViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HourMarkerViewItem.xib; sourceTree = "<group>"; }; 357391862507277500D30819 /* HourMarkerViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HourMarkerViewItem.xib; sourceTree = "<group>"; };
@ -890,6 +892,7 @@
35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */, 35584D1727F0B019006E3EAD /* DateFormatterManagerTests.swift */,
35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */, 35584D1927F0B64E006E3EAD /* AppDelegateTests.swift */,
35D23E3627F27E2E00C6DD55 /* ReviewControllerTests.swift */, 35D23E3627F27E2E00C6DD55 /* ReviewControllerTests.swift */,
35621CFB27F66C1900926D5C /* SearchDataSourceTests.swift */,
); );
path = ClockerUnitTests; path = ClockerUnitTests;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1279,6 +1282,7 @@
35D23E3727F27E2E00C6DD55 /* ReviewControllerTests.swift in Sources */, 35D23E3727F27E2E00C6DD55 /* ReviewControllerTests.swift in Sources */,
35584D1A27F0B64E006E3EAD /* AppDelegateTests.swift in Sources */, 35584D1A27F0B64E006E3EAD /* AppDelegateTests.swift in Sources */,
9A0385BB269E3434003B5E72 /* StandardMenubarHandlerTests.swift in Sources */, 9A0385BB269E3434003B5E72 /* StandardMenubarHandlerTests.swift in Sources */,
35621CFC27F66C1900926D5C /* SearchDataSourceTests.swift in Sources */,
35584D1827F0B019006E3EAD /* DateFormatterManagerTests.swift in Sources */, 35584D1827F0B019006E3EAD /* DateFormatterManagerTests.swift in Sources */,
C20839CA21515C1E00C86589 /* ClockerUnitTests.swift in Sources */, C20839CA21515C1E00C86589 /* ClockerUnitTests.swift in Sources */,
); );

68
Clocker/ClockerUnitTests/AppDelegateTests.swift

@ -1,12 +1,11 @@
// Copyright © 2015 Abhishek Banthia // Copyright © 2015 Abhishek Banthia
import XCTest
import CoreModelKit import CoreModelKit
import XCTest
@testable import Clocker @testable import Clocker
class AppDelegateTests: XCTestCase { class AppDelegateTests: XCTestCase {
func testStatusItemIsInitialized() throws { func testStatusItemIsInitialized() throws {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let statusHandler = subject?.statusItemForPanel() let statusHandler = subject?.statusItemForPanel()
@ -18,58 +17,58 @@ class AppDelegateTests: XCTestCase {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let dockMenu = subject?.applicationDockMenu(NSApplication.shared) let dockMenu = subject?.applicationDockMenu(NSApplication.shared)
let items = dockMenu?.items ?? [] let items = dockMenu?.items ?? []
XCTAssertEqual(dockMenu?.title, "Quick Access") XCTAssertEqual(dockMenu?.title, "Quick Access")
XCTAssertEqual(items.first?.title, "Toggle Panel") XCTAssertEqual(items.first?.title, "Toggle Panel")
XCTAssertEqual(items[1].title, "Preferences") XCTAssertEqual(items[1].title, "Preferences")
XCTAssertEqual(items[1].keyEquivalent, ",") XCTAssertEqual(items[1].keyEquivalent, ",")
XCTAssertEqual(items[2].title, "Hide from Dock") XCTAssertEqual(items[2].title, "Hide from Dock")
// Test selections // Test selections
XCTAssertEqual(items.first?.action, #selector(AppDelegate.togglePanel(_:))) XCTAssertEqual(items.first?.action, #selector(AppDelegate.togglePanel(_:)))
XCTAssertEqual(items[2].action, #selector(AppDelegate.hideFromDock)) XCTAssertEqual(items[2].action, #selector(AppDelegate.hideFromDock))
items.forEach { menuItem in items.forEach { menuItem in
XCTAssertTrue(menuItem.isEnabled) XCTAssertTrue(menuItem.isEnabled)
} }
} }
func testSetupMenubarTimer() { func testSetupMenubarTimer() {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let statusItemHandler = subject?.statusItemForPanel() let statusItemHandler = subject?.statusItemForPanel()
XCTAssertEqual(statusItemHandler?.statusItem.autosaveName, NSStatusItem.AutosaveName("ClockerStatusItem")) XCTAssertEqual(statusItemHandler?.statusItem.autosaveName, NSStatusItem.AutosaveName("ClockerStatusItem"))
} }
func testFloatingWindow() { func testFloatingWindow() {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let previousWindows = NSApplication.shared.windows let previousWindows = NSApplication.shared.windows
XCTAssertTrue(previousWindows.count >= 1) // Only the status bar window should be present XCTAssertTrue(previousWindows.count >= 1) // Only the status bar window should be present
subject?.setupFloatingWindow(true) subject?.setupFloatingWindow(true)
let floatingWindow = NSApplication.shared.windows.first { window in let floatingWindow = NSApplication.shared.windows.first { window in
if ((window.windowController as? FloatingWindowController) != nil) { if (window.windowController as? FloatingWindowController) != nil {
return true return true
} }
return false return false
} }
XCTAssertNotNil(floatingWindow) XCTAssertNotNil(floatingWindow)
XCTAssertEqual(floatingWindow?.windowController?.windowFrameAutosaveName, NSWindow.FrameAutosaveName("FloatingWindowAutoSave")) XCTAssertEqual(floatingWindow?.windowController?.windowFrameAutosaveName, NSWindow.FrameAutosaveName("FloatingWindowAutoSave"))
subject?.setupFloatingWindow(false) subject?.setupFloatingWindow(false)
let closedFloatingWindow = NSApplication.shared.windows.first { window in let closedFloatingWindow = NSApplication.shared.windows.first { window in
if ((window.windowController as? FloatingWindowController) != nil) { if (window.windowController as? FloatingWindowController) != nil {
return true return true
} }
return false return false
} }
XCTAssertNotNil(closedFloatingWindow) XCTAssertNotNil(closedFloatingWindow)
} }
func testActivationPolicy() { func testActivationPolicy() {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let previousOption = UserDefaults.standard.integer(forKey: CLAppDisplayOptions) let previousOption = UserDefaults.standard.integer(forKey: CLAppDisplayOptions)
@ -78,11 +77,11 @@ class AppDelegateTests: XCTestCase {
} else { } else {
XCTAssertEqual(NSApp.activationPolicy(), .regular) XCTAssertEqual(NSApp.activationPolicy(), .regular)
} }
subject?.hideFromDock() subject?.hideFromDock()
XCTAssertEqual(NSApp.activationPolicy(), .accessory) XCTAssertEqual(NSApp.activationPolicy(), .accessory)
} }
func testMenubarInvalidationToIcon() { func testMenubarInvalidationToIcon() {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
subject?.invalidateMenubarTimer(true) subject?.invalidateMenubarTimer(true)
@ -93,10 +92,10 @@ class AppDelegateTests: XCTestCase {
XCTAssertEqual(statusItemHandler?.statusItem.button?.imagePosition, .imageOnly) XCTAssertEqual(statusItemHandler?.statusItem.button?.imagePosition, .imageOnly)
XCTAssertEqual(statusItemHandler?.statusItem.toolTip, "Clocker") XCTAssertEqual(statusItemHandler?.statusItem.toolTip, "Clocker")
} }
func testCompactModeMenubarSetup() { func testCompactModeMenubarSetup() {
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let timezone1 = TimezoneData() let timezone1 = TimezoneData()
timezone1.timezoneID = TimeZone.autoupdatingCurrent.identifier timezone1.timezoneID = TimeZone.autoupdatingCurrent.identifier
timezone1.formattedAddress = "MenubarTimezone" timezone1.formattedAddress = "MenubarTimezone"
@ -104,23 +103,23 @@ class AppDelegateTests: XCTestCase {
// Encode it in UserDefaults // Encode it in UserDefaults
let encodedTimezone = NSKeyedArchiver.archivedData(withRootObject: timezone1) let encodedTimezone = NSKeyedArchiver.archivedData(withRootObject: timezone1)
DataStore.shared().setTimezones([encodedTimezone]) DataStore.shared().setTimezones([encodedTimezone])
subject?.setupMenubarTimer() subject?.setupMenubarTimer()
let statusItemHandler = subject?.statusItemForPanel() let statusItemHandler = subject?.statusItemForPanel()
XCTAssertNotNil(statusItemHandler?.statusItem.view) // This won't be nil for compact mode XCTAssertNotNil(statusItemHandler?.statusItem.view) // This won't be nil for compact mode
DataStore.shared().setTimezones([]) DataStore.shared().setTimezones([])
} }
func testStandardModeMenubarSetup() { func testStandardModeMenubarSetup() {
UserDefaults.standard.set(1, forKey: CLMenubarCompactMode) // Set the menubar mode to standard UserDefaults.standard.set(1, forKey: CLMenubarCompactMode) // Set the menubar mode to standard
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
let statusItemHandler = subject?.statusItemForPanel() let statusItemHandler = subject?.statusItemForPanel()
subject?.setupMenubarTimer() subject?.setupMenubarTimer()
XCTAssertEqual(statusItemHandler?.statusItem.button?.image?.name(), "LightModeIcon") XCTAssertEqual(statusItemHandler?.statusItem.button?.image?.name(), "LightModeIcon")
let timezone1 = TimezoneData() let timezone1 = TimezoneData()
timezone1.timezoneID = TimeZone.autoupdatingCurrent.identifier timezone1.timezoneID = TimeZone.autoupdatingCurrent.identifier
timezone1.formattedAddress = "MenubarTimezone" timezone1.formattedAddress = "MenubarTimezone"
@ -128,27 +127,26 @@ class AppDelegateTests: XCTestCase {
// Encode it in UserDefaults // Encode it in UserDefaults
let encodedTimezone = NSKeyedArchiver.archivedData(withRootObject: timezone1) let encodedTimezone = NSKeyedArchiver.archivedData(withRootObject: timezone1)
DataStore.shared().setTimezones([encodedTimezone]) DataStore.shared().setTimezones([encodedTimezone])
subject?.setupMenubarTimer() subject?.setupMenubarTimer()
XCTAssertNil(subject?.statusItemForPanel().statusItem.view) // This will be nil for standard mode XCTAssertNil(subject?.statusItemForPanel().statusItem.view) // This will be nil for standard mode
DataStore.shared().setTimezones([]) DataStore.shared().setTimezones([])
UserDefaults.standard.set(0, forKey: CLMenubarCompactMode) // Set the menubar mode back to compact UserDefaults.standard.set(0, forKey: CLMenubarCompactMode) // Set the menubar mode back to compact
} }
func testTogglingPanel() { func testTogglingPanel() {
UserDefaults.standard.set(1, forKey: CLShowAppInForeground) UserDefaults.standard.set(1, forKey: CLShowAppInForeground)
let subject = NSApplication.shared.delegate as? AppDelegate let subject = NSApplication.shared.delegate as? AppDelegate
subject?.ping("MockArgument") subject?.ping("MockArgument")
UserDefaults.standard.set(0, forKey: CLShowAppInForeground) UserDefaults.standard.set(0, forKey: CLShowAppInForeground)
let hasActiveGetter = PanelController.shared().hasActivePanel let hasActiveGetter = PanelController.shared().hasActivePanel
subject?.ping("MockArgument") subject?.ping("MockArgument")
XCTAssertNotEqual(hasActiveGetter, PanelController.shared().hasActivePanel) XCTAssertNotEqual(hasActiveGetter, PanelController.shared().hasActivePanel)
} }
} }

15
Clocker/ClockerUnitTests/ClockerUnitTests.swift

@ -392,30 +392,29 @@ class ClockerUnitTests: XCTestCase {
XCTAssertNotNil(convertedDate) XCTAssertNotNil(convertedDate)
} }
} }
func testStringFiltering() { func testStringFiltering() {
let stringWithComma = "Mumbai, Maharashtra" let stringWithComma = "Mumbai, Maharashtra"
let stringWithoutComma = "Mumbai" let stringWithoutComma = "Mumbai"
let emptyString = "" let emptyString = ""
XCTAssertEqual(stringWithComma.filteredName(), "Mumbai") XCTAssertEqual(stringWithComma.filteredName(), "Mumbai")
XCTAssertEqual(stringWithoutComma.filteredName(), "Mumbai") XCTAssertEqual(stringWithoutComma.filteredName(), "Mumbai")
XCTAssertEqual(emptyString.filteredName(), "") XCTAssertEqual(emptyString.filteredName(), "")
} }
func testToasty() { func testToasty() {
let view = NSView(frame: CGRect.zero) let view = NSView(frame: CGRect.zero)
view.makeToast("Hello, this is a toast") view.makeToast("Hello, this is a toast")
XCTAssertEqual(view.subviews.first?.accessibilityIdentifier(), "ToastView") XCTAssertEqual(view.subviews.first?.accessibilityIdentifier(), "ToastView")
let expectation = expectation(description: "Toast View should hide after 1 second") let expectation = expectation(description: "Toast View should hide after 1 second")
let result = XCTWaiter.wait(for: [expectation], timeout: 1.5) // Set 2 seconds here for a little leeway let result = XCTWaiter.wait(for: [expectation], timeout: 1.5) // Set 2 seconds here for a little leeway
if result == XCTWaiter.Result.timedOut { if result == XCTWaiter.Result.timedOut {
XCTAssertTrue(view.subviews.isEmpty) XCTAssertTrue(view.subviews.isEmpty)
} }
} }
func testPointingHandButton() { func testPointingHandButton() {
let sampleRect = CGRect(x: 0, y: 0, width: 200, height: 200) let sampleRect = CGRect(x: 0, y: 0, width: 200, height: 200)
let pointingHandCursorButton = PointingHandCursorButton(frame: CGRect.zero) let pointingHandCursorButton = PointingHandCursorButton(frame: CGRect.zero)
@ -423,7 +422,7 @@ class ClockerUnitTests: XCTestCase {
pointingHandCursorButton.resetCursorRects() pointingHandCursorButton.resetCursorRects()
XCTAssertEqual(pointingHandCursorButton.pointingHandCursor, NSCursor.pointingHand) XCTAssertEqual(pointingHandCursorButton.pointingHandCursor, NSCursor.pointingHand)
} }
func testNoTimezoneView() { func testNoTimezoneView() {
let sampleRect = CGRect(x: 0, y: 0, width: 200, height: 200) let sampleRect = CGRect(x: 0, y: 0, width: 200, height: 200)
let subject = NoTimezoneView(frame: sampleRect) let subject = NoTimezoneView(frame: sampleRect)

6
Clocker/ClockerUnitTests/DateFormatterManagerTests.swift

@ -5,7 +5,6 @@ import XCTest
@testable import Clocker @testable import Clocker
class DateFormatterManagerTests: XCTestCase { class DateFormatterManagerTests: XCTestCase {
func testRegularDateFormatter() throws { func testRegularDateFormatter() throws {
let subject = DateFormatterManager.dateFormatter(with: .medium, for: "UTC") let subject = DateFormatterManager.dateFormatter(with: .medium, for: "UTC")
XCTAssertEqual(subject.dateStyle, .medium) XCTAssertEqual(subject.dateStyle, .medium)
@ -13,7 +12,7 @@ class DateFormatterManagerTests: XCTestCase {
XCTAssertEqual(subject.locale.identifier, "en_US") XCTAssertEqual(subject.locale.identifier, "en_US")
XCTAssertEqual(subject.timeZone.identifier, "GMT") XCTAssertEqual(subject.timeZone.identifier, "GMT")
} }
func testDateFormatterWithFormat() throws { func testDateFormatterWithFormat() throws {
let subject = DateFormatterManager.dateFormatterWithFormat(with: .none, format: "hh:mm a", timezoneIdentifier: "Asia/Calcutta") let subject = DateFormatterManager.dateFormatterWithFormat(with: .none, format: "hh:mm a", timezoneIdentifier: "Asia/Calcutta")
XCTAssertEqual(subject.dateStyle, .none) XCTAssertEqual(subject.dateStyle, .none)
@ -23,7 +22,7 @@ class DateFormatterManagerTests: XCTestCase {
XCTAssertEqual(subject.locale.identifier, "en_US") XCTAssertEqual(subject.locale.identifier, "en_US")
XCTAssertEqual(subject.dateFormat, "hh:mm a") XCTAssertEqual(subject.dateFormat, "hh:mm a")
} }
func testLocalizedDateFormatter() throws { func testLocalizedDateFormatter() throws {
let subject = DateFormatterManager.localizedFormatter(with: "hh:mm:ss", for: "America/Los_Angeles") let subject = DateFormatterManager.localizedFormatter(with: "hh:mm:ss", for: "America/Los_Angeles")
XCTAssertEqual(subject.dateStyle, .none) XCTAssertEqual(subject.dateStyle, .none)
@ -32,5 +31,4 @@ class DateFormatterManagerTests: XCTestCase {
XCTAssertEqual(subject.timeZone.identifier, "America/Los_Angeles") XCTAssertEqual(subject.timeZone.identifier, "America/Los_Angeles")
XCTAssertEqual(subject.dateFormat, "hh:mm:ss") XCTAssertEqual(subject.dateFormat, "hh:mm:ss")
} }
} }

75
Clocker/ClockerUnitTests/ReviewControllerTests.swift

@ -1,7 +1,7 @@
// Copyright © 2015 Abhishek Banthia // Copyright © 2015 Abhishek Banthia
import XCTest
@testable import Clocker @testable import Clocker
import XCTest
class ReviewControllerTests: XCTestCase { class ReviewControllerTests: XCTestCase {
func testDebuggingMode() throws { func testDebuggingMode() throws {
@ -9,14 +9,14 @@ class ReviewControllerTests: XCTestCase {
return return
} }
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
// Call it again to ensure Keys.install // Call it again to ensure Keys.install
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
ReviewController.setPreviewMode(true) ReviewController.setPreviewMode(true)
XCTAssertTrue(ReviewController.canPrompt()) XCTAssertTrue(ReviewController.canPrompt())
} }
func testPromptNotDisplayedInFirstWeekSinceInstall() { func testPromptNotDisplayedInFirstWeekSinceInstall() {
guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker1") else { guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker1") else {
return return
@ -25,10 +25,10 @@ class ReviewControllerTests: XCTestCase {
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
// Explicitly set preview mode to false // Explicitly set preview mode to false
ReviewController.setPreviewMode(false) ReviewController.setPreviewMode(false)
XCTAssertFalse(ReviewController.canPrompt()) XCTAssertFalse(ReviewController.canPrompt())
} }
func testPrompDisplayedAfterFirstWeekOfInstall() { func testPrompDisplayedAfterFirstWeekOfInstall() {
let dateChunk = TimeChunk(seconds: 0, let dateChunk = TimeChunk(seconds: 0,
minutes: 0, minutes: 0,
@ -38,21 +38,21 @@ class ReviewControllerTests: XCTestCase {
months: 0, months: 0,
years: 0) years: 0)
let oldDate = Date().subtract(dateChunk) let oldDate = Date().subtract(dateChunk)
guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker2") else { guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker2") else {
return return
} }
mockDefaults.set(oldDate, forKey: "install") mockDefaults.set(oldDate, forKey: "install")
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
// Explicitly set preview mode to false // Explicitly set preview mode to false
ReviewController.setPreviewMode(false) ReviewController.setPreviewMode(false)
XCTAssertNil(mockDefaults.object(forKey:"last-prompt")) XCTAssertNil(mockDefaults.object(forKey: "last-prompt"))
XCTAssertNil(mockDefaults.object(forKey:"last-version")) XCTAssertNil(mockDefaults.object(forKey: "last-version"))
XCTAssertTrue(ReviewController.canPrompt()) XCTAssertTrue(ReviewController.canPrompt())
} }
func testPromptDisplayAfterTwoMonths() { func testPromptDisplayAfterTwoMonths() {
let dateChunk = TimeChunk(seconds: 0, let dateChunk = TimeChunk(seconds: 0,
minutes: 0, minutes: 0,
@ -62,16 +62,16 @@ class ReviewControllerTests: XCTestCase {
months: 0, months: 0,
years: 0) years: 0)
let minInstall = Date().subtract(dateChunk) let minInstall = Date().subtract(dateChunk)
let promptChunk = TimeChunk(seconds: 0, let promptChunk = TimeChunk(seconds: 0,
minutes: 0, minutes: 0,
hours: 0, hours: 0,
days: 60, days: 60,
weeks: 0, weeks: 0,
months: 0, months: 0,
years: 0) years: 0)
let lastPromptDate = Date().subtract(promptChunk) let lastPromptDate = Date().subtract(promptChunk)
guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker3") else { guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker3") else {
return return
} }
@ -79,12 +79,12 @@ class ReviewControllerTests: XCTestCase {
mockDefaults.set("test-version", forKey: "last-version") mockDefaults.set("test-version", forKey: "last-version")
mockDefaults.set(lastPromptDate, forKey: "last-prompt") mockDefaults.set(lastPromptDate, forKey: "last-prompt")
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
// Explicitly set preview mode to false // Explicitly set preview mode to false
ReviewController.setPreviewMode(false) ReviewController.setPreviewMode(false)
XCTAssertFalse(ReviewController.canPrompt()) XCTAssertFalse(ReviewController.canPrompt())
} }
func testPrompDisplayedAfterThreeMonths() { func testPrompDisplayedAfterThreeMonths() {
let dateChunk = TimeChunk(seconds: 0, let dateChunk = TimeChunk(seconds: 0,
minutes: 0, minutes: 0,
@ -94,16 +94,16 @@ class ReviewControllerTests: XCTestCase {
months: 0, months: 0,
years: 0) years: 0)
let minInstall = Date().subtract(dateChunk) let minInstall = Date().subtract(dateChunk)
let promptChunk = TimeChunk(seconds: 0, let promptChunk = TimeChunk(seconds: 0,
minutes: 0, minutes: 0,
hours: 0, hours: 0,
days: 91, days: 91,
weeks: 0, weeks: 0,
months: 0, months: 0,
years: 0) years: 0)
let lastPromptDate = Date().subtract(promptChunk) let lastPromptDate = Date().subtract(promptChunk)
guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker4") else { guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker4") else {
return return
} }
@ -111,23 +111,22 @@ class ReviewControllerTests: XCTestCase {
mockDefaults.set("test-version", forKey: "last-version") mockDefaults.set("test-version", forKey: "last-version")
mockDefaults.set(lastPromptDate, forKey: "last-prompt") mockDefaults.set(lastPromptDate, forKey: "last-prompt")
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
// Explicitly set preview mode to false // Explicitly set preview mode to false
ReviewController.setPreviewMode(false) ReviewController.setPreviewMode(false)
XCTAssertNotNil(mockDefaults.object(forKey:"last-prompt")) XCTAssertNotNil(mockDefaults.object(forKey: "last-prompt"))
XCTAssertNotNil(mockDefaults.object(forKey:"last-version")) XCTAssertNotNil(mockDefaults.object(forKey: "last-version"))
XCTAssertTrue(ReviewController.canPrompt()) XCTAssertTrue(ReviewController.canPrompt())
} }
func testPrompted() { func testPrompted() {
guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker5") else { guard let mockDefaults = UserDefaults(suiteName: "com.test.Clocker5") else {
return return
} }
ReviewController.applicationDidLaunch(mockDefaults) ReviewController.applicationDidLaunch(mockDefaults)
ReviewController.prompt() ReviewController.prompt()
XCTAssertNotNil(mockDefaults.object(forKey:"last-prompt")) XCTAssertNotNil(mockDefaults.object(forKey: "last-prompt"))
XCTAssertNotNil(mockDefaults.object(forKey:"last-version")) XCTAssertNotNil(mockDefaults.object(forKey: "last-version"))
} }
} }

139
Clocker/ClockerUnitTests/SearchDataSourceTests.swift

@ -0,0 +1,139 @@
// Copyright © 2015 Abhishek Banthia
import CoreModelKit
import XCTest
@testable import Clocker
class SearchDataSourceTests: XCTestCase {
private var subject: SearchDataSource!
private func setupSubject(searchText: String = "") {
let mockSearchField = NSSearchField()
mockSearchField.stringValue = searchText
subject = SearchDataSource(with: mockSearchField, location: .preferences)
}
private func setupMockData() {
subject.searchTimezones("los")
XCTAssertTrue(subject.calculateChangesets())
let mockTimezone = TimezoneData()
mockTimezone.timezoneID = "PST"
mockTimezone.formattedAddress = "Los Angeles"
subject.setFilteredArrayValue([mockTimezone])
subject.searchTimezones("los")
XCTAssertTrue(subject.calculateChangesets())
}
override func tearDownWithError() throws {
subject = nil
try super.tearDownWithError()
}
func testSearchTimezones() {
setupSubject(searchText: "")
// Test capitalized string
subject.searchTimezones("MUMBAI")
XCTAssert(subject.timezoneFilteredArray.isEmpty == false)
// Test sentence-cased string
subject.searchTimezones("Delhi")
XCTAssert(subject.timezoneFilteredArray.isEmpty == false)
// Test lower-cased string
subject.searchTimezones("california")
XCTAssert(subject.timezoneFilteredArray.isEmpty == false)
}
func testCalculateChangesets() {
setupSubject(searchText: "los")
setupMockData()
subject.cleanupFilterArray()
subject.searchTimezones("los")
XCTAssertTrue(subject.calculateChangesets())
}
func testRetrieveResult() throws {
setupSubject(searchText: "los")
setupMockData()
// 0 will translate to a city search result
let result1 = subject.retrieveResult(0)
let unwrap = try XCTUnwrap(result1)
if let metadata = unwrap as? CoreModelKit.TimezoneData {
XCTAssert(metadata.timezoneID == "PST")
}
// 1 will translate to a timezone search result
let result2 = subject.retrieveResult(1)
let unwrap2 = try XCTUnwrap(result2)
if let metadata = unwrap2 as? TimezoneMetadata {
XCTAssert(metadata.timezone.name == "America/Tijuana")
}
// Test placeForRow
let rowType = subject.placeForRow(0)
XCTAssert(rowType == .city)
let rowType1 = subject.placeForRow(1)
XCTAssert(rowType1 == .timezone)
// Test count
XCTAssertEqual(subject.resultsCount(), 4)
// Test retrieveFilteredResultFromGoogleAPI
let firstResult = try XCTUnwrap(subject.retrieveFilteredResultFromGoogleAPI(0))
XCTAssert(firstResult.timezoneID == "PST")
// filteredArray should only have a count of 1
XCTAssertNil(subject.retrieveFilteredResultFromGoogleAPI(1))
}
func testTableViewDataSourceMethods() {
let mockTableView = NSTableView(frame: CGRect.zero)
setupSubject(searchText: "los")
setupMockData()
let resultsCount = subject.numberOfRows(in: mockTableView)
XCTAssert(resultsCount == 4)
XCTAssert(subject.tableView(mockTableView, heightOfRow: 0) == 30)
}
func testRetrieveSelectedTimezone() {
setupSubject(searchText: "los")
setupMockData()
let result = subject.retrieveSelectedTimezone(0)
XCTAssert(result.timezone.abbreviation == "PDT")
}
func testRetrieveSelectedTimezoneWithEmptySearchField() {
// Setup subject with an empty search field
setupSubject(searchText: CLEmptyString)
subject.searchTimezones("los")
XCTAssertFalse(subject.calculateChangesets())
let mockTimezone = TimezoneData()
mockTimezone.timezoneID = "PST"
mockTimezone.formattedAddress = "Los Angeles"
subject.setFilteredArrayValue([mockTimezone])
subject.searchTimezones("los")
XCTAssertFalse(subject.calculateChangesets())
let result = subject.retrieveSelectedTimezone(1)
XCTAssert(result.timezone.abbreviation == "GMT")
}
func testRetrieveSelectedTimezoneWithEmptySearchFieldWithoutSearchResults() {
// Setup subject with an empty search field
setupSubject(searchText: "los")
setupMockData()
subject.cleanupFilterArray()
let result = subject.retrieveResult(0)
XCTAssertNil(result)
}
}

20
Clocker/ClockerUnitTests/ThemerTests.swift

@ -38,22 +38,22 @@ class ThemerTests: XCTestCase {
let expectedForwardsImage: String let expectedForwardsImage: String
let expectedResetSliderImage: String let expectedResetSliderImage: String
} }
@available(macOS 10.14, *) @available(macOS 10.14, *)
func testSettingTheme() { func testSettingTheme() {
// Set to some random number should set to 0 // Set to some random number should set to 0
let subject = Themer(index: 124) let subject = Themer(index: 124)
XCTAssertEqual(NSAppearance(named: .aqua), NSAppearance(named: .aqua)) XCTAssertEqual(NSAppearance(named: .aqua), NSAppearance(named: .aqua))
// Set the same theme; this should return early // Set the same theme; this should return early
subject.set(theme: 0) subject.set(theme: 0)
// Set the theme to dark theme // Set the theme to dark theme
subject.set(theme: 1) subject.set(theme: 1)
let expectedApperance = NSAppearance(named: .darkAqua) let expectedApperance = NSAppearance(named: .darkAqua)
XCTAssertEqual(expectedApperance, NSApp.appearance) XCTAssertEqual(expectedApperance, NSApp.appearance)
} }
func testLightTheme() throws { func testLightTheme() throws {
let subject = Themer(index: 0) // 0 is for light theme let subject = Themer(index: 0) // 0 is for light theme
let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9), let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9),
@ -85,7 +85,7 @@ class ThemerTests: XCTestCase {
expectedResetSliderImage: "xmark.circle.fill") expectedResetSliderImage: "xmark.circle.fill")
testSubject(subject: subject, withExpectatations: expectedThemeElements) testSubject(subject: subject, withExpectatations: expectedThemeElements)
} }
func testDarkTheme() throws { func testDarkTheme() throws {
let subject = Themer(index: 1) // 1 is for dark theme let subject = Themer(index: 1) // 1 is for dark theme
let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9), let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9),
@ -119,10 +119,10 @@ class ThemerTests: XCTestCase {
testSubject(subject: subject, withExpectatations: expectedThemeElements) testSubject(subject: subject, withExpectatations: expectedThemeElements)
XCTAssertEqual(subject.description, "Current Theme is \(Themer.Theme.dark)") XCTAssertEqual(subject.description, "Current Theme is \(Themer.Theme.dark)")
} }
func testSystemTheme() throws { func testSystemTheme() throws {
let currentSystemTheme = let currentSystemTheme =
UserDefaults.standard.string(forKey: CLAppleInterfaceStyleKey)?.lowercased().contains("dark") ?? false ? Themer.Theme.dark : Themer.Theme.light UserDefaults.standard.string(forKey: CLAppleInterfaceStyleKey)?.lowercased().contains("dark") ?? false ? Themer.Theme.dark : Themer.Theme.light
let subject = Themer(index: 2) // 2 is for system theme let subject = Themer(index: 2) // 2 is for system theme
let expectedSliderKnobColor = currentSystemTheme == .light ? NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9) : NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9) let expectedSliderKnobColor = currentSystemTheme == .light ? NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9) : NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9)
let expectedSliderRightColor = currentSystemTheme == .dark ? NSColor.white : NSColor.gray let expectedSliderRightColor = currentSystemTheme == .dark ? NSColor.white : NSColor.gray
@ -160,7 +160,7 @@ class ThemerTests: XCTestCase {
testSubject(subject: subject, withExpectatations: expectedThemeElements) testSubject(subject: subject, withExpectatations: expectedThemeElements)
XCTAssertEqual(subject.description, "System Theme is \(currentSystemTheme == .dark ? Themer.Theme.dark : Themer.Theme.light)") XCTAssertEqual(subject.description, "System Theme is \(currentSystemTheme == .dark ? Themer.Theme.dark : Themer.Theme.light)")
} }
func testSolarizedLightTheme() throws { func testSolarizedLightTheme() throws {
let subject = Themer(index: 3) // 3 is for solarized light theme let subject = Themer(index: 3) // 3 is for solarized light theme
let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9), let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 255.0, green: 255.0, blue: 255, alpha: 0.9),
@ -193,7 +193,7 @@ class ThemerTests: XCTestCase {
expectedResetSliderImage: "xmark.circle.fill") expectedResetSliderImage: "xmark.circle.fill")
testSubject(subject: subject, withExpectatations: expectedThemeElements) testSubject(subject: subject, withExpectatations: expectedThemeElements)
} }
func testSolarizedDarkTheme() throws { func testSolarizedDarkTheme() throws {
let subject = Themer(index: 4) // 4 is for solarized dark theme let subject = Themer(index: 4) // 4 is for solarized dark theme
let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9), let expectedThemeElements = ThemeExpectations(expectedSliderKnobColor: NSColor(deviceRed: 0.0, green: 0.0, blue: 0, alpha: 0.9),
@ -226,7 +226,7 @@ class ThemerTests: XCTestCase {
expectedResetSliderImage: "xmark.circle.fill") expectedResetSliderImage: "xmark.circle.fill")
testSubject(subject: subject, withExpectatations: expectedThemeElements) testSubject(subject: subject, withExpectatations: expectedThemeElements)
} }
private func testSubject(subject: Themer, withExpectatations expectations: ThemeExpectations) { private func testSubject(subject: Themer, withExpectatations expectations: ThemeExpectations) {
XCTAssertEqual(subject.sliderKnobColor(), expectations.expectedSliderKnobColor) XCTAssertEqual(subject.sliderKnobColor(), expectations.expectedSliderKnobColor)
XCTAssertEqual(subject.sliderRightColor(), expectations.expectedSliderRightColor) XCTAssertEqual(subject.sliderRightColor(), expectations.expectedSliderRightColor)

6
Clocker/CoreLoggerKit/Package.swift

@ -6,13 +6,13 @@ import PackageDescription
let package = Package( let package = Package(
name: "CoreLoggerKit", name: "CoreLoggerKit",
platforms: [ platforms: [
.macOS(.v10_12) .macOS(.v10_12),
], ],
products: [ products: [
.library( .library(
name: "CoreLoggerKit", name: "CoreLoggerKit",
targets: ["CoreLoggerKit"] targets: ["CoreLoggerKit"]
) ),
], ],
dependencies: [], dependencies: [],
targets: [ targets: [
@ -23,6 +23,6 @@ let package = Package(
.testTarget( .testTarget(
name: "CoreLoggerKitTests", name: "CoreLoggerKitTests",
dependencies: ["CoreLoggerKit"] dependencies: ["CoreLoggerKit"]
) ),
] ]
) )

2
Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/CoreLoggerKitTests.swift

@ -3,6 +3,6 @@ import XCTest
final class CoreLoggerKitTests: XCTestCase { final class CoreLoggerKitTests: XCTestCase {
static var allTests = [ static var allTests = [
("testExample", testExample) ("testExample", testExample),
] ]
} }

2
Clocker/CoreLoggerKit/Tests/CoreLoggerKitTests/XCTestManifests.swift

@ -3,7 +3,7 @@ import XCTest
#if !canImport(ObjectiveC) #if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] { public func allTests() -> [XCTestCaseEntry] {
return [ return [
testCase(CoreLoggerKitTests.allTests) testCase(CoreLoggerKitTests.allTests),
] ]
} }
#endif #endif

8
Clocker/CoreModelKit/Package.swift

@ -6,19 +6,19 @@ import PackageDescription
let package = Package( let package = Package(
name: "CoreModelKit", name: "CoreModelKit",
platforms: [ platforms: [
.macOS(.v10_12) .macOS(.v10_12),
], ],
products: [ products: [
// Products define the executables and libraries a package produces, and make them visible to other packages. // Products define the executables and libraries a package produces, and make them visible to other packages.
.library( .library(
name: "CoreModelKit", name: "CoreModelKit",
targets: ["CoreModelKit"] targets: ["CoreModelKit"]
) ),
], ],
dependencies: [ dependencies: [
// Dependencies declare other packages that this package depends on. // Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"), // .package(url: /* package url */, from: "1.0.0"),
.package(path: "../CoreLoggerKit/") .package(path: "../CoreLoggerKit/"),
], ],
targets: [ targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets are the basic building blocks of a package. A target can define a module or a test suite.
@ -30,6 +30,6 @@ let package = Package(
.testTarget( .testTarget(
name: "CoreModelKitTests", name: "CoreModelKitTests",
dependencies: ["CoreModelKit", "CoreLoggerKit"] dependencies: ["CoreModelKit", "CoreLoggerKit"]
) ),
] ]
) )

2
Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift

@ -66,7 +66,7 @@ public class TimezoneData: NSObject, NSCoding {
// Suffix // Suffix
NSNumber(integerLiteral: 9): DateFormat.twelveHourWithoutSuffix, NSNumber(integerLiteral: 9): DateFormat.twelveHourWithoutSuffix,
NSNumber(integerLiteral: 10): DateFormat.twelveHourWithoutSuffixAndSeconds, NSNumber(integerLiteral: 10): DateFormat.twelveHourWithoutSuffixAndSeconds,
NSNumber(integerLiteral: 11): DateFormat.epochTime NSNumber(integerLiteral: 11): DateFormat.epochTime,
] ]
public var customLabel: String? public var customLabel: String?

2
Clocker/CoreModelKit/Tests/CoreModelKitTests/XCTestManifests.swift

@ -3,7 +3,7 @@ import XCTest
#if !canImport(ObjectiveC) #if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] { public func allTests() -> [XCTestCaseEntry] {
return [ return [
testCase(CoreModelKitTests.allTests) testCase(CoreModelKitTests.allTests),
] ]
} }
#endif #endif

6
Clocker/Events and Reminders/CalendarHandler.swift

@ -391,7 +391,8 @@ extension EventCenter {
// Check for Zoom links // Check for Zoom links
if actualLink.contains("zoom.us/j/") if actualLink.contains("zoom.us/j/")
|| actualLink.contains("zoom.us/s/") || actualLink.contains("zoom.us/s/")
|| actualLink.contains("zoom.us/w/") { || actualLink.contains("zoom.us/w/")
{
// Create a Zoom App link // Create a Zoom App link
let workspace = NSWorkspace.shared let workspace = NSWorkspace.shared
if workspace.urlForApplication(toOpen: URL(string: "zoommtg://")!) != nil { if workspace.urlForApplication(toOpen: URL(string: "zoommtg://")!) != nil {
@ -417,7 +418,8 @@ extension EventCenter {
|| actualLink.contains("public.senfcall.de") || actualLink.contains("public.senfcall.de")
|| actualLink.contains("youcanbook.me/zoom/") || actualLink.contains("youcanbook.me/zoom/")
|| actualLink.contains("workplace.com/groupcall") || actualLink.contains("workplace.com/groupcall")
|| actualLink.contains("bluejeans.com/") { || actualLink.contains("bluejeans.com/")
{
if let meetingLink = result.url { if let meetingLink = result.url {
return meetingLink return meetingLink
} }

3
Clocker/Events and Reminders/RemindersHandler.swift

@ -51,7 +51,8 @@ extension EventCenter {
timezone: String, timezone: String,
alertIndex: Int, alertIndex: Int,
reminderDate: Date, reminderDate: Date,
additionalNotes: String?) -> Bool { additionalNotes: String?) -> Bool
{
initializeStoreIfNeccesary() initializeStoreIfNeccesary()
if reminderAccessNotDetermined() || reminderAccessDenied() { if reminderAccessNotDetermined() || reminderAccessDenied() {

10
Clocker/Menu Bar/StatusContainerView.swift

@ -31,10 +31,12 @@ func compactWidth(for timezone: TimezoneData) -> Int {
if timeFormat == DateFormat.twelveHour if timeFormat == DateFormat.twelveHour
|| timeFormat == DateFormat.twelveHourWithSeconds || timeFormat == DateFormat.twelveHourWithSeconds
|| timeFormat == DateFormat.twelveHourWithZero || timeFormat == DateFormat.twelveHourWithZero
|| timeFormat == DateFormat.twelveHourWithSeconds { || timeFormat == DateFormat.twelveHourWithSeconds
{
totalWidth += 20 totalWidth += 20
} else if timeFormat == DateFormat.twentyFourHour } else if timeFormat == DateFormat.twentyFourHour
|| timeFormat == DateFormat.twentyFourHourWithSeconds { || timeFormat == DateFormat.twentyFourHourWithSeconds
{
totalWidth += 0 totalWidth += 0
} }
@ -75,7 +77,7 @@ class StatusContainerView: NSView {
let timeBasedAttributes = [ let timeBasedAttributes = [
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
func containerWidth(for timezones: [Data]) -> CGFloat { func containerWidth(for timezones: [Data]) -> CGFloat {
@ -134,7 +136,7 @@ class StatusContainerView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
let operation = TimezoneDataOperations(with: timezone) let operation = TimezoneDataOperations(with: timezone)

3
Clocker/Menu Bar/StatusItemHandler.swift

@ -112,7 +112,8 @@ class StatusItemHandler: NSObject {
userNotificationsDidChangeNotif = center.addObserver(forName: UserDefaults.didChangeNotification, userNotificationsDidChangeNotif = center.addObserver(forName: UserDefaults.didChangeNotification,
object: self, object: self,
queue: mainQueue) { _ in queue: mainQueue)
{ _ in
self.setupStatusItem() self.setupStatusItem()
} }
} }

8
Clocker/Menu Bar/StatusItemView.swift

@ -49,7 +49,7 @@ class StatusItemView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return attributes return attributes
} }
@ -61,7 +61,7 @@ class StatusItemView: NSView {
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10),
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return textFontAttributes return textFontAttributes
} }
@ -90,14 +90,14 @@ class StatusItemView: NSView {
locationView.leadingAnchor.constraint(equalTo: leadingAnchor), locationView.leadingAnchor.constraint(equalTo: leadingAnchor),
locationView.trailingAnchor.constraint(equalTo: trailingAnchor), locationView.trailingAnchor.constraint(equalTo: trailingAnchor),
locationView.topAnchor.constraint(equalTo: topAnchor, constant: 7), locationView.topAnchor.constraint(equalTo: topAnchor, constant: 7),
locationView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35) locationView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35),
]) ])
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
timeView.leadingAnchor.constraint(equalTo: leadingAnchor), timeView.leadingAnchor.constraint(equalTo: leadingAnchor),
timeView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0), timeView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0),
timeView.topAnchor.constraint(equalTo: locationView.bottomAnchor), timeView.topAnchor.constraint(equalTo: locationView.bottomAnchor),
timeView.bottomAnchor.constraint(equalTo: bottomAnchor) timeView.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
} }

7
Clocker/Onboarding/OnboardingSearchController.swift

@ -135,7 +135,8 @@ class OnboardingSearchController: NSViewController {
private func setupLabelHidingTimer() { private func setupLabelHidingTimer() {
Timer.scheduledTimer(withTimeInterval: 5, Timer.scheduledTimer(withTimeInterval: 5,
repeats: false) { _ in repeats: false)
{ _ in
OperationQueue.main.addOperation { OperationQueue.main.addOperation {
self.setInfoLabel(CLEmptyString) self.setInfoLabel(CLEmptyString)
} }
@ -227,7 +228,7 @@ class OnboardingSearchController: NSViewController {
"latitude": latitude, "latitude": latitude,
"longitude": longitude, "longitude": longitude,
"nextUpdate": CLEmptyString, "nextUpdate": CLEmptyString,
CLCustomLabel: filteredAddress CLCustomLabel: filteredAddress,
] as [String: Any] ] as [String: Any]
DataStore.shared().addTimezone(TimezoneData(with: newTimeZone)) DataStore.shared().addTimezone(TimezoneData(with: newTimeZone))
@ -413,7 +414,7 @@ class OnboardingSearchController: NSViewController {
CLTimezoneName: formattedAddress, CLTimezoneName: formattedAddress,
CLCustomLabel: formattedAddress, CLCustomLabel: formattedAddress,
CLTimezoneID: CLEmptyString, CLTimezoneID: CLEmptyString,
CLPlaceIdentifier: result.placeId CLPlaceIdentifier: result.placeId,
] as [String: Any] ] as [String: Any]
return TimezoneData(with: totalPackage) return TimezoneData(with: totalPackage)

4
Clocker/Overall App/ConfigExport.swift

@ -29,7 +29,7 @@ struct ConfigExport {
CLDefaultMenubarMode, CLDefaultMenubarMode,
CLInstallHomeIndicatorObject, CLInstallHomeIndicatorObject,
CLSwitchToCompactModeAlert, CLSwitchToCompactModeAlert,
CLDisplayDSTTransitionInfo CLDisplayDSTTransitionInfo,
]) ])
let dictionaryRep = UserDefaults.standard.dictionaryRepresentation() let dictionaryRep = UserDefaults.standard.dictionaryRepresentation()
var clockerPrefs: [String: Any] = [:] var clockerPrefs: [String: Any] = [:]
@ -53,7 +53,7 @@ struct ConfigExport {
"Latitude": customObject.latitude ?? 0.0, "Latitude": customObject.latitude ?? 0.0,
"Longitude": customObject.longitude ?? 0.0, "Longitude": customObject.longitude ?? 0.0,
"Place Identifier": customObject.placeID ?? "0.0", "Place Identifier": customObject.placeID ?? "0.0",
"Selection Type": "\(customObject.selectionType)" "Selection Type": "\(customObject.selectionType)",
] ]
return timezoneDictionary return timezoneDictionary
} }

1
Clocker/Overall App/DateFormatterManager.swift

@ -3,7 +3,6 @@
import Cocoa import Cocoa
class DateFormatterManager: NSObject { class DateFormatterManager: NSObject {
private static var dateFormatter = DateFormatter() private static var dateFormatter = DateFormatter()
private static var calendarDateFormatter = DateFormatter() private static var calendarDateFormatter = DateFormatter()
private static var simpleFormatter = DateFormatter() private static var simpleFormatter = DateFormatter()

3
Clocker/Overall App/Themer.swift

@ -459,7 +459,8 @@ extension Themer {
_ darkImage: NSImage, _ darkImage: NSImage,
_ systemImage: NSImage, _ systemImage: NSImage,
_ solarizedLightImage: NSImage, _ solarizedLightImage: NSImage,
_ solarizedDarkImage: NSImage) -> NSImage { _ solarizedDarkImage: NSImage) -> NSImage
{
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
case .light: case .light:

2
Clocker/Panel/Data Layer/TimezoneDataOperations.swift

@ -283,7 +283,7 @@ extension TimezoneDataOperations {
let unableToConvertDateParameters = [ let unableToConvertDateParameters = [
"New Date": newDate, "New Date": newDate,
"Timezone": dataObject.timezone(), "Timezone": dataObject.timezone(),
"Locale": dateFormatter.locale.identifier "Locale": dateFormatter.locale.identifier,
] as [String: Any] ] as [String: Any]
Logger.log(object: unableToConvertDateParameters, for: "Date conversion failure - New Date is nil") Logger.log(object: unableToConvertDateParameters, for: "Date conversion failure - New Date is nil")
return CLEmptyString return CLEmptyString

10
Clocker/Panel/Notes Popover/NotesPopover.swift

@ -73,7 +73,7 @@ class NotesPopover: NSViewController {
"1 hour before", "1 hour before",
"2 hour before", "2 hour before",
"1 day before", "1 day before",
"2 days before" "2 days before",
] ]
alertPopupButton.removeAllItems() alertPopupButton.removeAllItems()
@ -240,7 +240,7 @@ class NotesPopover: NSViewController {
let attributesDictionary = [ let attributesDictionary = [
NSAttributedString.Key.font: font, NSAttributedString.Key.font: font,
NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor(), NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor(),
NSAttributedString.Key.paragraphStyle: style NSAttributedString.Key.paragraphStyle: style,
] ]
button.attributedTitle = NSAttributedString(string: title, button.attributedTitle = NSAttributedString(string: title,
@ -322,7 +322,8 @@ class NotesPopover: NSViewController {
} }
private func updateTimezoneInDefaultPreferences(with override: Int, private func updateTimezoneInDefaultPreferences(with override: Int,
_: OverrideType) { _: OverrideType)
{
let timezones = DataStore.shared().timezones() let timezones = DataStore.shared().timezones()
var timezoneObjects: [TimezoneData] = [] var timezoneObjects: [TimezoneData] = []
@ -391,7 +392,8 @@ class NotesPopover: NSViewController {
timezone: model.timezone(), timezone: model.timezone(),
alertIndex: alertIndex, alertIndex: alertIndex,
reminderDate: reminderPicker.dateValue, reminderDate: reminderPicker.dateValue,
additionalNotes: model.note) { additionalNotes: model.note)
{
showSuccessMessage() showSuccessMessage()
} }
} }

2
Clocker/Panel/Notes Popover/TextViewWithPlaceholder.swift

@ -18,7 +18,7 @@ class TextViewWithPlaceholder: NSTextView {
if let placeHolderFont = NSFont(name: "Avenir", size: 14) { if let placeHolderFont = NSFont(name: "Avenir", size: 14) {
let textDict = [ let textDict = [
NSAttributedString.Key.foregroundColor: NSColor.gray, NSAttributedString.Key.foregroundColor: NSColor.gray,
NSAttributedString.Key.font: placeHolderFont NSAttributedString.Key.font: placeHolderFont,
] ]
return NSAttributedString(string: " Add your notes here.", attributes: textDict) return NSAttributedString(string: " Add your notes here.", attributes: textDict)
} }

5
Clocker/Panel/PanelController.swift

@ -154,7 +154,8 @@ class PanelController: ParentPanelController {
} }
if let statusWindow = statusBackgroundWindow, if let statusWindow = statusBackgroundWindow,
let statusButton = statusView { let statusButton = statusView
{
var statusItemFrame = statusWindow.convertToScreen(statusButton.frame) var statusItemFrame = statusWindow.convertToScreen(statusButton.frame)
var statusItemScreen = NSScreen.main var statusItemScreen = NSScreen.main
var testPoint = statusItemFrame.origin var testPoint = statusItemFrame.origin
@ -221,7 +222,7 @@ class PanelController: ParentPanelController {
"Show Upcoming Event View": showUpcomingEventView == "YES" ? "Yes" : "No", "Show Upcoming Event View": showUpcomingEventView == "YES" ? "Yes" : "No",
"Country": country, "Country": country,
"Calendar Access Provided": EventCenter.sharedCenter().calendarAccessGranted() ? "Yes" : "No", "Calendar Access Provided": EventCenter.sharedCenter().calendarAccessGranted() ? "Yes" : "No",
"Number of Timezones": preferences.count "Number of Timezones": preferences.count,
] ]
Logger.log(object: panelEvent, for: "openedPanel") Logger.log(object: panelEvent, for: "openedPanel")

35
Clocker/Panel/ParentPanelController.swift

@ -172,12 +172,12 @@ class ParentPanelController: NSWindowController {
setupObservers() setupObservers()
updateReviewViewFontColor() updateReviewViewFontColor()
// Set the background color of the bottom buttons view to something different to indicate we're not in a release candidate // Set the background color of the bottom buttons view to something different to indicate we're not in a release candidate
#if DEBUG #if DEBUG
stackView.arrangedSubviews.last?.layer?.backgroundColor = NSColor(deviceRed: 255.0/255.0, stackView.arrangedSubviews.last?.layer?.backgroundColor = NSColor(deviceRed: 255.0 / 255.0,
green: 150.0/255.0, green: 150.0 / 255.0,
blue: 122.0/255.0, blue: 122.0 / 255.0,
alpha: 0.5).cgColor alpha: 0.5).cgColor
stackView.arrangedSubviews.last?.toolTip = "Clocker is running in Debug Mode" stackView.arrangedSubviews.last?.toolTip = "Clocker is running in Debug Mode"
#endif #endif
@ -197,7 +197,8 @@ class ParentPanelController: NSWindowController {
object: nil) object: nil)
NotificationCenter.default.addObserver(forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification, NotificationCenter.default.addObserver(forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification,
object: self, object: self,
queue: OperationQueue.main) { [weak self] _ in queue: OperationQueue.main)
{ [weak self] _ in
if let sSelf = self { if let sSelf = self {
sSelf.mainTableView.reloadData() sSelf.mainTableView.reloadData()
sSelf.setScrollViewConstraint() sSelf.setScrollViewConstraint()
@ -349,7 +350,7 @@ class ParentPanelController: NSWindowController {
let styleAttributes = [ let styleAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13) ?? NSFont.systemFont(ofSize: 13) NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13) ?? NSFont.systemFont(ofSize: 13),
] ]
let leftButtonAttributedTitle = NSAttributedString(string: leftButton.title, attributes: styleAttributes) let leftButtonAttributedTitle = NSAttributedString(string: leftButton.title, attributes: styleAttributes)
@ -425,7 +426,8 @@ class ParentPanelController: NSWindowController {
newHeight += 20 newHeight += 20
} else if DataStore.shared().shouldDisplay(.dstTransitionInfo), } else if DataStore.shared().shouldDisplay(.dstTransitionInfo),
let obj = object, let obj = object,
TimezoneDataOperations(with: obj).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) != nil { TimezoneDataOperations(with: obj).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) != nil
{
newHeight += 20 newHeight += 20
} }
} }
@ -613,7 +615,8 @@ class ParentPanelController: NSWindowController {
if $0 < mainTableView.numberOfRows, if $0 < mainTableView.numberOfRows,
let cellView = mainTableView.view(atColumn: 0, row: $0, makeIfNecessary: false) as? TimezoneCellView, let cellView = mainTableView.view(atColumn: 0, row: $0, makeIfNecessary: false) as? TimezoneCellView,
let model = TimezoneData.customObject(from: current) { let model = TimezoneData.customObject(from: current)
{
if let futureSliderCell = futureSlider.cell as? CustomSliderCell, futureSliderCell.tracking == true { if let futureSliderCell = futureSlider.cell as? CustomSliderCell, futureSliderCell.tracking == true {
return return
} }
@ -633,7 +636,8 @@ class ParentPanelController: NSWindowController {
if let note = model.note, !note.isEmpty { if let note = model.note, !note.isEmpty {
cellView.noteLabel.stringValue = note cellView.noteLabel.stringValue = note
} else if DataStore.shared().shouldDisplay(.dstTransitionInfo), } else if DataStore.shared().shouldDisplay(.dstTransitionInfo),
let value = TimezoneDataOperations(with: model).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue) { let value = TimezoneDataOperations(with: model).nextDaylightSavingsTransitionIfAvailable(with: futureSliderValue)
{
cellView.noteLabel.stringValue = value cellView.noteLabel.stringValue = value
} else { } else {
cellView.noteLabel.stringValue = CLEmptyString cellView.noteLabel.stringValue = CLEmptyString
@ -733,7 +737,8 @@ class ParentPanelController: NSWindowController {
@IBAction func calendarButtonAction(_ sender: NSButton) { @IBAction func calendarButtonAction(_ sender: NSButton) {
if sender.title == NSLocalizedString("Click here to start.", if sender.title == NSLocalizedString("Click here to start.",
comment: "Button Title for no Calendar access") { comment: "Button Title for no Calendar access")
{
showPermissionsWindow() showPermissionsWindow()
} else { } else {
retrieveCalendarEvents() retrieveCalendarEvents()
@ -824,7 +829,8 @@ class ParentPanelController: NSWindowController {
if let events = eventCenter.eventsForDate[NSCalendar.autoupdatingCurrent.startOfDay(for: now)], events.isEmpty == false { if let events = eventCenter.eventsForDate[NSCalendar.autoupdatingCurrent.startOfDay(for: now)], events.isEmpty == false {
OperationQueue.main.addOperation { OperationQueue.main.addOperation {
if self.upcomingEventCollectionView != nil, if self.upcomingEventCollectionView != nil,
let upcomingEvents = eventCenter.upcomingEventsForDay(events) { let upcomingEvents = eventCenter.upcomingEventsForDay(events)
{
self.upcomingEventsDataSource.updateEventsDataSource(upcomingEvents) self.upcomingEventsDataSource.updateEventsDataSource(upcomingEvents)
self.upcomingEventCollectionView.reloadData() self.upcomingEventCollectionView.reloadData()
return return
@ -904,7 +910,7 @@ class ParentPanelController: NSWindowController {
let styleAttributes = [ let styleAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)! NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)!,
] ]
leftButton.attributedTitle = NSAttributedString(string: "Not Really", attributes: styleAttributes) leftButton.attributedTitle = NSAttributedString(string: "Not Really", attributes: styleAttributes)
rightButton.attributedTitle = NSAttributedString(string: "Yes!", attributes: styleAttributes) rightButton.attributedTitle = NSAttributedString(string: "Yes!", attributes: styleAttributes)
@ -940,7 +946,7 @@ class ParentPanelController: NSWindowController {
let styleAttributes = [ let styleAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)! NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)!,
] ]
if leftButton.attributedTitle.string == "Not Really" { if leftButton.attributedTitle.string == "Not Really" {
@ -1124,7 +1130,8 @@ extension ParentPanelController: NSSharingServicePickerDelegate {
stride(from: 0, to: sortedByTime.count, by: 1).forEach { stride(from: 0, to: sortedByTime.count, by: 1).forEach {
if $0 < sortedByTime.count, if $0 < sortedByTime.count,
let dataModel = TimezoneData.customObject(from: sortedByTime[$0]) { let dataModel = TimezoneData.customObject(from: sortedByTime[$0])
{
let dataOperations = TimezoneDataOperations(with: dataModel) let dataOperations = TimezoneDataOperations(with: dataModel)
let date = dataOperations.todaysDate(with: 0) let date = dataOperations.todaysDate(with: 0)
let time = dataOperations.time(with: 0) let time = dataOperations.time(with: 0)

2
Clocker/Panel/UI/PanelTableView.swift

@ -32,7 +32,7 @@ class PanelTableView: NSTableView {
let options: NSTrackingArea.Options = [ let options: NSTrackingArea.Options = [
.mouseMoved, .mouseMoved,
.mouseEnteredAndExited, .mouseEnteredAndExited,
.activeAlways .activeAlways,
] ]
let clipRect = enclosingScrollView?.contentView.bounds ?? .zero let clipRect = enclosingScrollView?.contentView.bounds ?? .zero

6
Clocker/Panel/UI/TimezoneCellView.swift

@ -199,7 +199,7 @@ class TimezoneCellView: NSTableCellView {
} }
override func mouseDown(with event: NSEvent) { override func mouseDown(with event: NSEvent) {
if (event.clickCount == 1) { if event.clickCount == 1 {
// Text is copied in the following format: Chicago - 1625185925 // Text is copied in the following format: Chicago - 1625185925
let clipboardCopy = "\(customName.stringValue) - \(time.stringValue)" let clipboardCopy = "\(customName.stringValue) - \(time.stringValue)"
let pasteboard = NSPasteboard.general let pasteboard = NSPasteboard.general
@ -209,8 +209,8 @@ class TimezoneCellView: NSTableCellView {
window?.contentView?.makeToast("Copied to Clipboard".localized()) window?.contentView?.makeToast("Copied to Clipboard".localized())
window?.endEditing(for: nil) window?.endEditing(for: nil)
} else if (event.clickCount == 2) { } else if event.clickCount == 2 {
//TODO: Favourite this timezone // TODO: Favourite this timezone
} }
} }

3
Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift

@ -40,7 +40,8 @@ class UpcomingEventViewItem: NSCollectionViewItem {
_ color: NSColor, _ color: NSColor,
_ link: URL?, _ link: URL?,
_ delegate: UpcomingEventPanelDelegate?, _ delegate: UpcomingEventPanelDelegate?,
_ isCancelled: Bool) { _ isCancelled: Bool)
{
if leadingConstraint.constant != UpcomingEventViewItem.EventLeadingConstraint / 2 { if leadingConstraint.constant != UpcomingEventViewItem.EventLeadingConstraint / 2 {
leadingConstraint.animator().constant = UpcomingEventViewItem.EventLeadingConstraint / 2 leadingConstraint.animator().constant = UpcomingEventViewItem.EventLeadingConstraint / 2
} }

2
Clocker/Preferences/About/PointingHandCursorButton.swift

@ -3,7 +3,7 @@
import Cocoa import Cocoa
class PointingHandCursorButton: NSButton { class PointingHandCursorButton: NSButton {
let pointingHandCursor: NSCursor = NSCursor.pointingHand let pointingHandCursor: NSCursor = .pointingHand
override func draw(_ dirtyRect: NSRect) { override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect) super.draw(dirtyRect)

5
Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift

@ -80,7 +80,8 @@ class AppFeedbackWindowController: NSWindowController {
themeDidChangeNotification = NotificationCenter.default.addObserver(forName: .themeDidChangeNotification, themeDidChangeNotification = NotificationCenter.default.addObserver(forName: .themeDidChangeNotification,
object: nil, object: nil,
queue: OperationQueue.main) { _ in queue: OperationQueue.main)
{ _ in
self.window?.backgroundColor = Themer.shared().mainBackgroundColor() self.window?.backgroundColor = Themer.shared().mainBackgroundColor()
self.setup() self.setup()
} }
@ -201,7 +202,7 @@ class AppFeedbackWindowController: NSWindowController {
AppFeedbackConstants.CLOperatingSystemVersion: osVersion, AppFeedbackConstants.CLOperatingSystemVersion: osVersion,
AppFeedbackConstants.CLClockerVersion: versionInfo, AppFeedbackConstants.CLClockerVersion: versionInfo,
AppFeedbackConstants.CLAppFeedbackDateProperty: todaysDate(), AppFeedbackConstants.CLAppFeedbackDateProperty: todaysDate(),
AppFeedbackConstants.CLAppFeedbackUserPreferences: generateUserPreferences() AppFeedbackConstants.CLAppFeedbackUserPreferences: generateUserPreferences(),
] ]
} }

5
Clocker/Preferences/Appearance/AppearanceViewController.swift

@ -60,7 +60,7 @@ class AppearanceViewController: ParentViewController {
"4 days", "4 days",
"5 days", "5 days",
"6 days", "6 days",
"7 days" "7 days",
]) ])
if #available(macOS 11.0, *) {} else { if #available(macOS 11.0, *) {} else {
@ -188,7 +188,8 @@ class AppearanceViewController: ParentViewController {
refresh(panel: true, floating: true) refresh(panel: true, floating: true)
if let selectedFormat = sender.selectedItem?.title, if let selectedFormat = sender.selectedItem?.title,
selectedFormat.contains("ss") { selectedFormat.contains("ss")
{
Logger.info("Selected format contains timezone format") Logger.info("Selected format contains timezone format")
guard let panelController = PanelController.panel() else { return } guard let panelController = PanelController.panel() else { return }
panelController.pauseTimer() panelController.pauseTimer()

8
Clocker/Preferences/Calendar/CalendarViewController.swift

@ -113,7 +113,7 @@ class CalendarViewController: ParentViewController {
let attributesDictionary: [NSAttributedString.Key: Any] = [ let attributesDictionary: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.paragraphStyle: style, NSAttributedString.Key.paragraphStyle: style,
NSAttributedString.Key.font: boldFont, NSAttributedString.Key.font: boldFont,
NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor() NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor(),
] ]
let attributedString = NSAttributedString(string: title, let attributedString = NSAttributedString(string: title,
attributes: attributesDictionary) attributes: attributesDictionary)
@ -242,13 +242,15 @@ extension CalendarViewController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor _: NSTableColumn?, row: Int) -> NSView? { func tableView(_ tableView: NSTableView, viewFor _: NSTableColumn?, row: Int) -> NSView? {
if let currentSource = calendars[row] as? String, if let currentSource = calendars[row] as? String,
let message = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "sourceCellView"), owner: self) as? SourceTableViewCell { let message = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "sourceCellView"), owner: self) as? SourceTableViewCell
{
message.sourceName.stringValue = currentSource message.sourceName.stringValue = currentSource
return message return message
} }
if let currentSource = calendars[row] as? CalendarInfo, if let currentSource = calendars[row] as? CalendarInfo,
let calendarCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "calendarCellView"), owner: self) as? CalendarTableViewCell { let calendarCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "calendarCellView"), owner: self) as? CalendarTableViewCell
{
calendarCell.calendarName.stringValue = currentSource.calendar.title calendarCell.calendarName.stringValue = currentSource.calendar.title
calendarCell.calendarSelected.state = currentSource.selected ? NSControl.StateValue.on : NSControl.StateValue.off calendarCell.calendarSelected.state = currentSource.selected ? NSControl.StateValue.on : NSControl.StateValue.off
calendarCell.calendarSelected.target = self calendarCell.calendarSelected.target = self

7
Clocker/Preferences/General/PreferencesDataSource.swift

@ -104,7 +104,8 @@ extension PreferencesDataSource: NSTableViewDataSource {
var selectedDataSource: TimezoneData? var selectedDataSource: TimezoneData?
if selectedTimezones.count > row, if selectedTimezones.count > row,
let model = TimezoneData.customObject(from: selectedTimezones[row]) { let model = TimezoneData.customObject(from: selectedTimezones[row])
{
selectedDataSource = model selectedDataSource = model
} }
@ -161,7 +162,7 @@ extension PreferencesDataSource: NSTableViewDataSource {
if selectedTimezones.count > row { if selectedTimezones.count > row {
Logger.log(object: [ Logger.log(object: [
"Old Label": dataObject.customLabel ?? "Error", "Old Label": dataObject.customLabel ?? "Error",
"New Label": formattedValue "New Label": formattedValue,
], ],
for: "Custom Label Changed") for: "Custom Label Changed")
@ -174,7 +175,7 @@ extension PreferencesDataSource: NSTableViewDataSource {
Logger.log(object: [ Logger.log(object: [
"MethodName": "SetObjectValue", "MethodName": "SetObjectValue",
"Selected Timezone Count": selectedTimezones.count, "Selected Timezone Count": selectedTimezones.count,
"Current Row": row "Current Row": row,
], ],
for: "Error in selected row count") for: "Error in selected row count")
} }

14
Clocker/Preferences/General/PreferencesViewController.swift

@ -95,7 +95,8 @@ class PreferencesViewController: ParentViewController {
NotificationCenter.default.addObserver(forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification, NotificationCenter.default.addObserver(forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification,
object: self, object: self,
queue: OperationQueue.main) { [weak self] _ in queue: OperationQueue.main)
{ [weak self] _ in
if let sSelf = self { if let sSelf = self {
sSelf.refreshTimezoneTableView() sSelf.refreshTimezoneTableView()
} }
@ -238,7 +239,7 @@ class PreferencesViewController: ParentViewController {
setupColor() setupColor()
startupCheckbox.integerValue = DataStore.shared().retrieve(key: CLStartAtLogin) as? Int ?? 0 startupCheckbox.integerValue = DataStore.shared().retrieve(key: CLStartAtLogin) as? Int ?? 0
searchField.bezelStyle = .roundedBezel searchField.bezelStyle = .roundedBezel
} }
@ -250,7 +251,7 @@ class PreferencesViewController: ParentViewController {
[timezoneNameSortButton, labelSortButton, timezoneSortButton].forEach { [timezoneNameSortButton, labelSortButton, timezoneSortButton].forEach {
$0?.attributedTitle = NSAttributedString(string: $0?.title ?? CLEmptyString, attributes: [ $0?.attributedTitle = NSAttributedString(string: $0?.title ?? CLEmptyString, attributes: [
NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor(), NSAttributedString.Key.foregroundColor: Themer.shared().mainTextColor(),
NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)! NSAttributedString.Key.font: NSFont(name: "Avenir-Light", size: 13)!,
]) ])
} }
@ -348,7 +349,8 @@ extension PreferencesViewController: NSTableViewDataSource, NSTableViewDelegate
if let appDelegate = NSApplication.shared.delegate as? AppDelegate, if let appDelegate = NSApplication.shared.delegate as? AppDelegate,
let menubarFavourites = DataStore.shared().menubarTimezones(), let menubarFavourites = DataStore.shared().menubarTimezones(),
menubarFavourites.isEmpty, menubarFavourites.isEmpty,
DataStore.shared().shouldDisplay(.showMeetingInMenubar) == false { DataStore.shared().shouldDisplay(.showMeetingInMenubar) == false
{
appDelegate.invalidateMenubarTimer(true) appDelegate.invalidateMenubarTimer(true)
} }
@ -512,7 +514,7 @@ extension PreferencesViewController {
CLTimezoneName: formattedAddress, CLTimezoneName: formattedAddress,
CLCustomLabel: formattedAddress, CLCustomLabel: formattedAddress,
CLTimezoneID: CLEmptyString, CLTimezoneID: CLEmptyString,
CLPlaceIdentifier: $0.placeId CLPlaceIdentifier: $0.placeId,
] as [String: Any] ] as [String: Any]
finalResults.append(TimezoneData(with: totalPackage)) finalResults.append(TimezoneData(with: totalPackage))
@ -604,7 +606,7 @@ extension PreferencesViewController {
"latitude": dataObject.latitude!, "latitude": dataObject.latitude!,
"longitude": dataObject.longitude!, "longitude": dataObject.longitude!,
"nextUpdate": CLEmptyString, "nextUpdate": CLEmptyString,
CLCustomLabel: filteredAddress CLCustomLabel: filteredAddress,
] as [String: Any] ] as [String: Any]
// Mark if the timezone is same as local timezone // Mark if the timezone is same as local timezone

42
Clocker/Preferences/General/SearchDataSource.swift

@ -102,27 +102,27 @@ class SearchDataSource: NSObject {
timezoneArray.append(utcTimezone) timezoneArray.append(utcTimezone)
for identifier in TimeZone.knownTimeZoneIdentifiers { for identifier in TimeZone.knownTimeZoneIdentifiers {
guard let timezoneObject = TimeZone(identifier: identifier) else { if let timezoneObject = TimeZone(identifier: identifier) {
continue // Force-cast explicity since we get the identifier from `knownTimeZoneIdentifiers`
let abbreviation = timezoneObject.abbreviation()!
let identifier = timezoneObject.identifier
var tags: Set<String> = [abbreviation.lowercased(), identifier.lowercased()]
var extraTags: [String] = []
if let tagsPresent = timezoneMetadataDictionary[abbreviation] {
extraTags = tagsPresent
}
extraTags.forEach { tag in
tags.insert(tag)
}
let timezoneIdentifier = NSTimeZone(name: identifier)!
let timezoneMetadata = TimezoneMetadata(timezone: timezoneIdentifier,
tags: tags,
formattedName: identifier,
abbreviation: abbreviation)
timezoneArray.append(timezoneMetadata)
} }
let abbreviation = timezoneObject.abbreviation() ?? "Empty"
let identifier = timezoneObject.identifier
var tags: Set<String> = [abbreviation.lowercased(), identifier.lowercased()]
var extraTags: [String] = []
if let tagsPresent = timezoneMetadataDictionary[abbreviation] {
extraTags = tagsPresent
}
extraTags.forEach { tag in
tags.insert(tag)
}
let timezoneIdentifier = NSTimeZone(name: identifier)!
let timezoneMetadata = TimezoneMetadata(timezone: timezoneIdentifier,
tags: tags,
formattedName: identifier,
abbreviation: abbreviation)
timezoneArray.append(timezoneMetadata)
} }
} }
@ -157,7 +157,7 @@ class SearchDataSource: NSObject {
timezoneFilteredArray = timezoneArray.filter { timezoneMetadata -> Bool in timezoneFilteredArray = timezoneArray.filter { timezoneMetadata -> Bool in
let tags = timezoneMetadata.tags let tags = timezoneMetadata.tags
for tag in tags where tag.contains(searchString) { for tag in tags where tag.contains(searchString.lowercased()) {
return true return true
} }
return false return false

21
Clocker/Preferences/Menu Bar/StatusContainerView.swift

@ -18,7 +18,7 @@ func bufferCalculatedWidth() -> Int {
if DataStore.shared().shouldShowDateInMenubar() { if DataStore.shared().shouldShowDateInMenubar() {
totalWidth += 20 totalWidth += 20
} }
if DataStore.shared().shouldDisplay(.showMeetingInMenubar) { if DataStore.shared().shouldDisplay(.showMeetingInMenubar) {
totalWidth += 100 totalWidth += 100
} }
@ -37,10 +37,12 @@ func compactWidth(for timezone: TimezoneData) -> Int {
if timeFormat == DateFormat.twelveHour if timeFormat == DateFormat.twelveHour
|| timeFormat == DateFormat.twelveHourWithSeconds || timeFormat == DateFormat.twelveHourWithSeconds
|| timeFormat == DateFormat.twelveHourWithZero || timeFormat == DateFormat.twelveHourWithZero
|| timeFormat == DateFormat.twelveHourWithSeconds { || timeFormat == DateFormat.twelveHourWithSeconds
{
totalWidth += 20 totalWidth += 20
} else if timeFormat == DateFormat.twentyFourHour } else if timeFormat == DateFormat.twentyFourHour
|| timeFormat == DateFormat.twentyFourHourWithSeconds { || timeFormat == DateFormat.twentyFourHourWithSeconds
{
totalWidth += 0 totalWidth += 0
} }
@ -81,7 +83,8 @@ class StatusContainerView: NSView {
if showUpcomingEventView, if showUpcomingEventView,
let events = EventCenter.sharedCenter().eventsForDate[NSCalendar.autoupdatingCurrent.startOfDay(for: Date())], let events = EventCenter.sharedCenter().eventsForDate[NSCalendar.autoupdatingCurrent.startOfDay(for: Date())],
events.isEmpty == false, events.isEmpty == false,
let upcomingEvent = EventCenter.sharedCenter().nextOccuring(events) { let upcomingEvent = EventCenter.sharedCenter().nextOccuring(events)
{
let calculatedWidth = bestWidth(for: upcomingEvent) let calculatedWidth = bestWidth(for: upcomingEvent)
let frame = NSRect(x: previousX, y: 0, width: calculatedWidth, height: 30) let frame = NSRect(x: previousX, y: 0, width: calculatedWidth, height: 30)
let calendarItemView = UpcomingEventStatusItemView(frame: frame) let calendarItemView = UpcomingEventStatusItemView(frame: frame)
@ -100,7 +103,7 @@ class StatusContainerView: NSView {
let timeBasedAttributes = [ let timeBasedAttributes = [
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
func containerWidth(for timezones: [Data]) -> CGFloat { func containerWidth(for timezones: [Data]) -> CGFloat {
@ -163,7 +166,7 @@ class StatusContainerView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
let operation = TimezoneDataOperations(with: timezone) let operation = TimezoneDataOperations(with: timezone)
@ -173,7 +176,7 @@ class StatusContainerView: NSView {
return Int(max(bestSize.width, bestTitleSize.width) + bufferWidth) return Int(max(bestSize.width, bestTitleSize.width) + bufferWidth)
} }
private func bestWidth(for eventInfo: EventInfo) -> Int { private func bestWidth(for eventInfo: EventInfo) -> Int {
var textColor = hasDarkAppearance ? NSColor.white : NSColor.black var textColor = hasDarkAppearance ? NSColor.white : NSColor.black
@ -185,7 +188,7 @@ class StatusContainerView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
let bestSize = compactModeTimeFont.size(eventInfo.metadataForMeeting(), let bestSize = compactModeTimeFont.size(eventInfo.metadataForMeeting(),
@ -202,7 +205,7 @@ class StatusContainerView: NSView {
if subviews.isEmpty { if subviews.isEmpty {
assertionFailure("Subviews count should > 0") assertionFailure("Subviews count should > 0")
} }
for view in subviews { for view in subviews {
if let conformingView = view as? StatusItemViewConforming { if let conformingView = view as? StatusItemViewConforming {
conformingView.statusItemViewSetNeedsDisplay() conformingView.statusItemViewSetNeedsDisplay()

7
Clocker/Preferences/Menu Bar/StatusItemHandler.swift

@ -115,7 +115,8 @@ class StatusItemHandler: NSObject {
userNotificationsDidChangeNotif = center.addObserver(forName: UserDefaults.didChangeNotification, userNotificationsDidChangeNotif = center.addObserver(forName: UserDefaults.didChangeNotification,
object: self, object: self,
queue: mainQueue) { _ in queue: mainQueue)
{ _ in
self.setupStatusItem() self.setupStatusItem()
} }
@ -202,7 +203,7 @@ class StatusItemHandler: NSObject {
let timezonesSupportingSeconds = syncedTimezones.filter { data in let timezonesSupportingSeconds = syncedTimezones.filter { data in
if let timezoneObj = TimezoneData.customObject(from: data) { if let timezoneObj = TimezoneData.customObject(from: data) {
return timezoneObj.shouldShowSeconds(DataStore.shared().timezoneFormat()) return timezoneObj.shouldShowSeconds(DataStore.shared().timezoneFormat())
} }
return false return false
} }
@ -361,7 +362,7 @@ class StatusItemHandler: NSObject {
constructCompactView(with: menubarTitleHandler.checkForUpcomingEvents() != nil) constructCompactView(with: menubarTitleHandler.checkForUpcomingEvents() != nil)
updateMenubar() updateMenubar()
} }
private func retrieveUpcomingEventStatusView() -> NSView? { private func retrieveUpcomingEventStatusView() -> NSView? {
let upcomingEventView = statusContainerView?.subviews.first(where: { statusItemView in let upcomingEventView = statusContainerView?.subviews.first(where: { statusItemView in
if let upcomingEventView = statusItemView as? StatusItemViewConforming { if let upcomingEventView = statusItemView as? StatusItemViewConforming {

8
Clocker/Preferences/Menu Bar/StatusItemView.swift

@ -50,7 +50,7 @@ class StatusItemView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return attributes return attributes
} }
@ -62,7 +62,7 @@ class StatusItemView: NSView {
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10),
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return textFontAttributes return textFontAttributes
} }
@ -91,14 +91,14 @@ class StatusItemView: NSView {
locationView.leadingAnchor.constraint(equalTo: leadingAnchor), locationView.leadingAnchor.constraint(equalTo: leadingAnchor),
locationView.trailingAnchor.constraint(equalTo: trailingAnchor), locationView.trailingAnchor.constraint(equalTo: trailingAnchor),
locationView.topAnchor.constraint(equalTo: topAnchor, constant: 7), locationView.topAnchor.constraint(equalTo: topAnchor, constant: 7),
locationView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35) locationView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35),
]) ])
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
timeView.leadingAnchor.constraint(equalTo: leadingAnchor), timeView.leadingAnchor.constraint(equalTo: leadingAnchor),
timeView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0), timeView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0),
timeView.topAnchor.constraint(equalTo: locationView.bottomAnchor), timeView.topAnchor.constraint(equalTo: locationView.bottomAnchor),
timeView.bottomAnchor.constraint(equalTo: bottomAnchor) timeView.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
} }

8
Clocker/Preferences/Menu Bar/UpcomingEventStatusItemView.swift

@ -21,7 +21,7 @@ class UpcomingEventStatusItemView: NSView {
NSAttributedString.Key.font: compactModeTimeFont, NSAttributedString.Key.font: compactModeTimeFont,
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return attributes return attributes
} }
@ -33,7 +33,7 @@ class UpcomingEventStatusItemView: NSView {
NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 10),
NSAttributedString.Key.foregroundColor: textColor, NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.backgroundColor: NSColor.clear, NSAttributedString.Key.backgroundColor: NSColor.clear,
NSAttributedString.Key.paragraphStyle: defaultParagraphStyle NSAttributedString.Key.paragraphStyle: defaultParagraphStyle,
] ]
return textFontAttributes return textFontAttributes
} }
@ -54,14 +54,14 @@ class UpcomingEventStatusItemView: NSView {
nextEventField.leadingAnchor.constraint(equalTo: leadingAnchor), nextEventField.leadingAnchor.constraint(equalTo: leadingAnchor),
nextEventField.trailingAnchor.constraint(equalTo: trailingAnchor), nextEventField.trailingAnchor.constraint(equalTo: trailingAnchor),
nextEventField.topAnchor.constraint(equalTo: topAnchor, constant: 7), nextEventField.topAnchor.constraint(equalTo: topAnchor, constant: 7),
nextEventField.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35) nextEventField.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.35),
]) ])
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
etaField.leadingAnchor.constraint(equalTo: leadingAnchor), etaField.leadingAnchor.constraint(equalTo: leadingAnchor),
etaField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0), etaField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0),
etaField.topAnchor.constraint(equalTo: nextEventField.bottomAnchor), etaField.topAnchor.constraint(equalTo: nextEventField.bottomAnchor),
etaField.bottomAnchor.constraint(equalTo: bottomAnchor) etaField.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
} }

6
Clocker/StartupKit/Package.swift

@ -6,13 +6,13 @@ import PackageDescription
let package = Package( let package = Package(
name: "StartupKit", name: "StartupKit",
platforms: [ platforms: [
.macOS(.v10_12) .macOS(.v10_12),
], ],
products: [ products: [
.library( .library(
name: "StartupKit", name: "StartupKit",
targets: ["StartupKit"] targets: ["StartupKit"]
) ),
], ],
dependencies: [ dependencies: [
// Dependencies declare other packages that this package depends on. // Dependencies declare other packages that this package depends on.
@ -22,6 +22,6 @@ let package = Package(
.target( .target(
name: "StartupKit", name: "StartupKit",
dependencies: [] dependencies: []
) ),
] ]
) )

Loading…
Cancel
Save