Browse Source

Some makeup.

pull/101/head
Abhishek 3 years ago
parent
commit
8cd3c8a55f
  1. 2
      Clocker/AppDelegate.swift
  2. 4
      Clocker/ClockerUITests/AboutUsTests.swift
  3. 2
      Clocker/ClockerUITests/CopyToClipboardTests.swift
  4. 33
      Clocker/ClockerUITests/PermissionsTests.swift
  5. 32
      Clocker/ClockerUnitTests/StandardMenubarHandlerTests.swift
  6. 8
      Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift
  7. 6
      Clocker/Dependencies/Date Additions/TimePeriodChain.swift
  8. 35
      Clocker/Events and Reminders/CalendarHandler.swift
  9. 3
      Clocker/Events and Reminders/RemindersHandler.swift
  10. 6
      Clocker/Menu Bar/StatusContainerView.swift
  11. 2
      Clocker/Menu Bar/StatusItemHandler.swift
  12. 12
      Clocker/Onboarding/OnboardingSearchController.swift
  13. 19
      Clocker/Overall App/ConfigExport.swift
  14. 2
      Clocker/Overall App/NetworkManager.swift
  15. 24
      Clocker/Overall App/Themer.swift
  16. 2
      Clocker/Panel/Data Layer/TimezoneDataOperations.swift
  17. 8
      Clocker/Panel/Notes Popover/NotesPopover.swift
  18. 23
      Clocker/Panel/PanelController.swift
  19. 10
      Clocker/Panel/ParentPanelController+ModernSlider.swift
  20. 96
      Clocker/Panel/ParentPanelController.swift
  21. 4
      Clocker/Panel/Rate Controller/ReviewController.swift
  22. 6
      Clocker/Panel/UI/TimezoneCellView.swift
  23. 2
      Clocker/Panel/UI/TimezoneDataSource.swift
  24. 22
      Clocker/Panel/Upcoming Events/ParentPanelController+UpcomingEvents.swift
  25. 10
      Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift
  26. 12
      Clocker/Panel/Upcoming Events/UpcomingEventsDataSource.swift
  27. 6
      Clocker/Preferences/About/AboutViewController.swift
  28. 31
      Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift
  29. 18
      Clocker/Preferences/Appearance/AppearanceViewController.swift
  30. 8
      Clocker/Preferences/Calendar/CalendarViewController.swift
  31. 7
      Clocker/Preferences/General/PreferencesDataSource.swift
  32. 21
      Clocker/Preferences/General/PreferencesViewController.swift
  33. 2
      Clocker/Preferences/General/SearchDataSource.swift
  34. 6
      Clocker/Preferences/Menu Bar/StatusContainerView.swift
  35. 2
      Clocker/Preferences/Menu Bar/StatusItemHandler.swift
  36. 15
      Clocker/Preferences/Menu Bar/UpcomingEventStatusItemView.swift
  37. 4
      Clocker/Preferences/OneWindowController.swift

2
Clocker/AppDelegate.swift

@ -16,7 +16,7 @@ open class AppDelegate: NSObject, NSApplicationDelegate {
panelObserver?.invalidate() panelObserver?.invalidate()
} }
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
if let path = keyPath, path == PreferencesConstants.hotKeyPathIdentifier { if let path = keyPath, path == PreferencesConstants.hotKeyPathIdentifier {
let hotKeyCenter = PTHotKeyCenter.shared() let hotKeyCenter = PTHotKeyCenter.shared()

4
Clocker/ClockerUITests/AboutUsTests.swift

@ -32,12 +32,12 @@ class AboutUsTests: XCTestCase {
app.buttons["Preferences"].click() app.buttons["Preferences"].click()
tapAboutTab() tapAboutTab()
app.checkBoxes["ClockerPrivateFeedback"].click() app.checkBoxes["ClockerPrivateFeedback"].click()
app.buttons["Send Feedback"].click() app.buttons["Send Feedback"].click()
XCTAssertFalse(app.progressIndicators["ProgressIndicator"].exists) XCTAssertFalse(app.progressIndicators["ProgressIndicator"].exists)
sleep(2) // Wait for Toast to disappear sleep(2) // Wait for Toast to disappear
// Close window // Close window

2
Clocker/ClockerUITests/CopyToClipboardTests.swift

@ -32,7 +32,7 @@ class CopyToClipboardTests: XCTestCase {
let actualValue = NSPasteboard.general.string(forType: .string) ?? "Empty Pasteboard" let actualValue = NSPasteboard.general.string(forType: .string) ?? "Empty Pasteboard"
XCTAssert(expectedValue == actualValue, XCTAssert(expectedValue == actualValue,
"Clipboard value (\(actualValue)) doesn't match expected result: \(expectedValue)") "Clipboard value (\(actualValue)) doesn't match expected result: \(expectedValue)")
// Test full copy // Test full copy
let cellCount = app.tables["FloatingTableView"].cells.count let cellCount = app.tables["FloatingTableView"].cells.count
var clipboardValue = String() var clipboardValue = String()

33
Clocker/ClockerUITests/PermissionsTests.swift

@ -16,28 +16,28 @@ class PermissionsTests: XCTestCase {
func testAcceptingCalendarPermissions() { func testAcceptingCalendarPermissions() {
app.tapMenubarIcon() app.tapMenubarIcon()
app/*@START_MENU_TOKEN@*/.buttons["Preferences"]/*[[".dialogs[\"Clocker Panel\"].buttons[\"Preferences\"]",".buttons[\"Preferences\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.click() app/*@START_MENU_TOKEN@*/.buttons["Preferences"]/*[[".dialogs[\"Clocker Panel\"].buttons[\"Preferences\"]",".buttons[\"Preferences\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.click()
let clockerWindow = app.windows["Clocker"] let clockerWindow = app.windows["Clocker"]
// Check Permissions first // Check Permissions first
let permissionsTab = clockerWindow.toolbars.buttons["Permissions"] let permissionsTab = clockerWindow.toolbars.buttons["Permissions"]
permissionsTab.click() permissionsTab.click()
let grantButton = clockerWindow.buttons["CalendarGrantAccessButton"].firstMatch let grantButton = clockerWindow.buttons["CalendarGrantAccessButton"].firstMatch
if grantButton.title == "Granted" || grantButton.title == "Denied" { if grantButton.title == "Granted" || grantButton.title == "Denied" {
return return
} }
let calendarButton = clockerWindow.toolbars.buttons["Calendar"] let calendarButton = clockerWindow.toolbars.buttons["Calendar"]
calendarButton.click() calendarButton.click()
let showUpcomingEventView = clockerWindow.staticTexts["UpcomingEventView"] let showUpcomingEventView = clockerWindow.staticTexts["UpcomingEventView"]
XCTAssertFalse(showUpcomingEventView.isHittable) XCTAssertFalse(showUpcomingEventView.isHittable)
clockerWindow.buttons["Grant Access"].click() clockerWindow.buttons["Grant Access"].click()
clockerWindow.buttons["CalendarGrantAccessButton"].firstMatch.click() clockerWindow.buttons["CalendarGrantAccessButton"].firstMatch.click()
addUIInterruptionMonitor(withDescription: "Calendars Access") { alert -> Bool in addUIInterruptionMonitor(withDescription: "Calendars Access") { alert -> Bool in
let alertButton = alert.buttons["OK"] let alertButton = alert.buttons["OK"]
if alertButton.exists { if alertButton.exists {
@ -46,29 +46,29 @@ class PermissionsTests: XCTestCase {
} }
return false return false
} }
calendarButton.click() calendarButton.click()
XCTAssertTrue(showUpcomingEventView.isHittable) XCTAssertTrue(showUpcomingEventView.isHittable)
} }
func testAcceptingRemindersPermissions() { func testAcceptingRemindersPermissions() {
app.tapMenubarIcon() app.tapMenubarIcon()
app/*@START_MENU_TOKEN@*/.buttons["Preferences"]/*[[".dialogs[\"Clocker Panel\"].buttons[\"Preferences\"]",".buttons[\"Preferences\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.click() app/*@START_MENU_TOKEN@*/.buttons["Preferences"]/*[[".dialogs[\"Clocker Panel\"].buttons[\"Preferences\"]",".buttons[\"Preferences\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.click()
let clockerWindow = app.windows["Clocker"] let clockerWindow = app.windows["Clocker"]
// Check Permissions first // Check Permissions first
let permissionsTab = clockerWindow.toolbars.buttons["Permissions"] let permissionsTab = clockerWindow.toolbars.buttons["Permissions"]
permissionsTab.click() permissionsTab.click()
let grantButton = clockerWindow.buttons["RemindersGrantAccessButton"].firstMatch let grantButton = clockerWindow.buttons["RemindersGrantAccessButton"].firstMatch
if grantButton.title == "Granted" || grantButton.title == "Denied" { if grantButton.title == "Granted" || grantButton.title == "Denied" {
return return
} }
clockerWindow.buttons["RemindersGrantAccessButton"].firstMatch.click() clockerWindow.buttons["RemindersGrantAccessButton"].firstMatch.click()
addUIInterruptionMonitor(withDescription: "Reminders Access") { alert -> Bool in addUIInterruptionMonitor(withDescription: "Reminders Access") { alert -> Bool in
let alertButton = alert.buttons["OK"] let alertButton = alert.buttons["OK"]
if alertButton.exists { if alertButton.exists {
@ -78,5 +78,4 @@ class PermissionsTests: XCTestCase {
return false return false
} }
} }
} }

32
Clocker/ClockerUnitTests/StandardMenubarHandlerTests.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 StandardMenubarHandlerTests: XCTestCase { class StandardMenubarHandlerTests: XCTestCase {
private let mumbai = ["customLabel": "Ghar", private let mumbai = ["customLabel": "Ghar",
"formattedAddress": "Mumbai", "formattedAddress": "Mumbai",
"place_id": "ChIJwe1EZjDG5zsRaYxkjY_tpF0", "place_id": "ChIJwe1EZjDG5zsRaYxkjY_tpF0",
@ -14,48 +13,48 @@ class StandardMenubarHandlerTests: XCTestCase {
"nextUpdate": "", "nextUpdate": "",
"latitude": "19.0759837", "latitude": "19.0759837",
"longitude": "72.8776559"] "longitude": "72.8776559"]
func testValidStandardMenubarHandler_returnMenubarTitle() { func testValidStandardMenubarHandler_returnMenubarTitle() {
// Wipe all timezones from UserDefaults // Wipe all timezones from UserDefaults
UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey) UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey)
// Save a menubar selected timezone // Save a menubar selected timezone
let dataObject = TimezoneData(with: mumbai) let dataObject = TimezoneData(with: mumbai)
dataObject.isFavourite = 1 dataObject.isFavourite = 1
let operationsObject = TimezoneDataOperations(with: dataObject) let operationsObject = TimezoneDataOperations(with: dataObject)
operationsObject.saveObject() operationsObject.saveObject()
let menubarTimezones = DataStore.shared().menubarTimezones() let menubarTimezones = DataStore.shared().menubarTimezones()
XCTAssertTrue(menubarTimezones?.count == 1) XCTAssertTrue(menubarTimezones?.count == 1)
// Set standard menubar in Prefs // Set standard menubar in Prefs
UserDefaults.standard.set(1, forKey: CLMenubarCompactMode) UserDefaults.standard.set(1, forKey: CLMenubarCompactMode)
let menubarHandler = MenubarHandler() let menubarHandler = MenubarHandler()
let menubarString = menubarHandler.titleForMenubar() ?? "" let menubarString = menubarHandler.titleForMenubar() ?? ""
// Test menubar string is present // Test menubar string is present
XCTAssertTrue(menubarString.count > 0) XCTAssertTrue(menubarString.count > 0)
XCTAssertTrue(menubarString.contains("Ghar")) XCTAssertTrue(menubarString.contains("Ghar"))
// Set default back to compact menubar // Set default back to compact menubar
UserDefaults.standard.set(0, forKey: CLMenubarCompactMode) UserDefaults.standard.set(0, forKey: CLMenubarCompactMode)
} }
func testUnfavouritedTimezone_returnEmptyMenubarTimezoneCount() { func testUnfavouritedTimezone_returnEmptyMenubarTimezoneCount() {
// Wipe all timezones from UserDefaults // Wipe all timezones from UserDefaults
UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey) UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey)
// Save a menubar selected timezone // Save a menubar selected timezone
let dataObject = TimezoneData(with: mumbai) let dataObject = TimezoneData(with: mumbai)
dataObject.isFavourite = 0 dataObject.isFavourite = 0
let operationsObject = TimezoneDataOperations(with: dataObject) let operationsObject = TimezoneDataOperations(with: dataObject)
operationsObject.saveObject() operationsObject.saveObject()
let menubarTimezones = DataStore.shared().menubarTimezones() let menubarTimezones = DataStore.shared().menubarTimezones()
XCTAssertTrue(menubarTimezones?.count == 0) XCTAssertTrue(menubarTimezones?.count == 0)
} }
func testUnfavouritedTimezone_returnNilMenubarString() { func testUnfavouritedTimezone_returnNilMenubarString() {
// Wipe all timezones from UserDefaults // Wipe all timezones from UserDefaults
UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey) UserDefaults.standard.setValue(nil, forKey: CLDefaultPreferenceKey)
@ -63,17 +62,16 @@ class StandardMenubarHandlerTests: XCTestCase {
let emptyMenubarString = menubarHandler.titleForMenubar() let emptyMenubarString = menubarHandler.titleForMenubar()
// Returns early because DataStore.menubarTimezones is nil // Returns early because DataStore.menubarTimezones is nil
XCTAssertNil(emptyMenubarString) XCTAssertNil(emptyMenubarString)
// Save a menubar selected timezone // Save a menubar selected timezone
let dataObject = TimezoneData(with: mumbai) let dataObject = TimezoneData(with: mumbai)
dataObject.isFavourite = 0 dataObject.isFavourite = 0
let operationsObject = TimezoneDataOperations(with: dataObject) let operationsObject = TimezoneDataOperations(with: dataObject)
operationsObject.saveObject() operationsObject.saveObject()
let menubarString = menubarHandler.titleForMenubar() ?? "" let menubarString = menubarHandler.titleForMenubar() ?? ""
// Test menubar string is absent // Test menubar string is absent
XCTAssertTrue(menubarString.count == 0) XCTAssertTrue(menubarString.count == 0)
} }
} }

8
Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift

@ -85,7 +85,7 @@ public class TimezoneData: NSObject, NSCoding {
public var isSystemTimezone = false public var isSystemTimezone = false
public var overrideFormat: TimezoneOverride = .globalFormat public var overrideFormat: TimezoneOverride = .globalFormat
override public init() { public override init() {
selectionType = .timezone selectionType = .timezone
isFavourite = 0 isFavourite = 0
note = ModelConstants.emptyString note = ModelConstants.emptyString
@ -277,7 +277,7 @@ public class TimezoneData: NSObject, NSCoding {
return formatInString.contains("ss") return formatInString.contains("ss")
} }
override public var hash: Int { public override var hash: Int {
guard let placeIdentifier = placeID, let timezone = timezoneID else { guard let placeIdentifier = placeID, let timezone = timezoneID else {
return -1 return -1
} }
@ -289,14 +289,14 @@ public class TimezoneData: NSObject, NSCoding {
return lhs.placeID == rhs.placeID return lhs.placeID == rhs.placeID
} }
override public func isEqual(to object: Any?) -> Bool { public override func isEqual(to object: Any?) -> Bool {
if let other = object as? TimezoneData { if let other = object as? TimezoneData {
return placeID == other.placeID return placeID == other.placeID
} }
return false return false
} }
override public func isEqual(_ object: Any?) -> Bool { public override func isEqual(_ object: Any?) -> Bool {
guard let compared = object as? TimezoneData else { guard let compared = object as? TimezoneData else {
return false return false
} }

6
Clocker/Dependencies/Date Additions/TimePeriodChain.swift

@ -138,15 +138,15 @@ open class TimePeriodChain: TimePeriodGroup {
_end = _end?.addingTimeInterval(duration) _end = _end?.addingTimeInterval(duration)
} }
override public func map<T>(_ transform: (TimePeriodProtocol) throws -> T) rethrows -> [T] { public override func map<T>(_ transform: (TimePeriodProtocol) throws -> T) rethrows -> [T] {
return try periods.map(transform) return try periods.map(transform)
} }
override public func filter(_ isIncluded: (TimePeriodProtocol) throws -> Bool) rethrows -> [TimePeriodProtocol] { public override func filter(_ isIncluded: (TimePeriodProtocol) throws -> Bool) rethrows -> [TimePeriodProtocol] {
return try periods.filter(isIncluded) return try periods.filter(isIncluded)
} }
override internal func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, TimePeriodProtocol) throws -> Result) rethrows -> Result { internal override func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, TimePeriodProtocol) throws -> Result) rethrows -> Result {
return try periods.reduce(initialResult, nextPartialResult) return try periods.reduce(initialResult, nextPartialResult)
} }

35
Clocker/Events and Reminders/CalendarHandler.swift

@ -160,9 +160,9 @@ extension EventCenter {
let filteredEvents = relevantEvents.filter { let filteredEvents = relevantEvents.filter {
$0.event.isAllDay == false && $0.event.startDate.timeIntervalSinceNow > -300 $0.event.isAllDay == false && $0.event.startDate.timeIntervalSinceNow > -300
} }
if filteredEvents.count == 1 { return filteredEvents.first } if filteredEvents.count == 1 { return filteredEvents.first }
// If there are multipl events coming up, prefer the ones the currentUser has accepted // If there are multipl events coming up, prefer the ones the currentUser has accepted
let acceptedEvents = filteredEvents.filter { let acceptedEvents = filteredEvents.filter {
$0.attendeStatus == .accepted $0.attendeStatus == .accepted
@ -170,16 +170,16 @@ extension EventCenter {
let optionalEvents = filteredEvents.filter { let optionalEvents = filteredEvents.filter {
$0.attendeStatus == .tentative $0.attendeStatus == .tentative
} }
if let firstAcceptedEvent = acceptedEvents.first { if let firstAcceptedEvent = acceptedEvents.first {
return firstAcceptedEvent return firstAcceptedEvent
} }
// If there are no accepted events, prefer the first optional event // If there are no accepted events, prefer the first optional event
if acceptedEvents.isEmpty && !optionalEvents.isEmpty { if acceptedEvents.isEmpty, !optionalEvents.isEmpty {
return optionalEvents.first return optionalEvents.first
} }
// Otherwise check if there's a filtered event at all and return it // Otherwise check if there's a filtered event at all and return it
if let first = filteredEvents.first { if let first = filteredEvents.first {
return first return first
@ -191,14 +191,14 @@ extension EventCenter {
return filteredAllDayEvent return filteredAllDayEvent
} }
func upcomingEventsForDay(_: [EventInfo]) -> [EventInfo]? { func upcomingEventsForDay(_: [EventInfo]) -> [EventInfo]? {
if calendarAccessDenied() || calendarAccessNotDetermined() { if calendarAccessDenied() || calendarAccessNotDetermined() {
return nil return nil
} }
let relevantEvents = filteredEvents[autoupdatingCalendar.startOfDay(for: Date())] ?? [] let relevantEvents = filteredEvents[autoupdatingCalendar.startOfDay(for: Date())] ?? []
return relevantEvents.filter { return relevantEvents.filter {
$0.event.startDate.timeIntervalSinceNow > -300 $0.event.startDate.timeIntervalSinceNow > -300
} }
@ -413,8 +413,7 @@ extension EventCenter {
|| actualLink.contains("indigo.collocall.de") || actualLink.contains("indigo.collocall.de")
|| 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") {
{
if let zoomLink = result.url { if let zoomLink = result.url {
return zoomLink return zoomLink
} }
@ -426,7 +425,7 @@ extension EventCenter {
private func retrieveMeetingURL(_ event: EKEvent) -> URL? { private func retrieveMeetingURL(_ event: EKEvent) -> URL? {
if EventCenter.dataDetector == nil { if EventCenter.dataDetector == nil {
var dataDetector: NSDataDetector? = nil var dataDetector: NSDataDetector?
do { do {
dataDetector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) dataDetector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
} catch { } catch {
@ -450,21 +449,21 @@ extension EventCenter {
return nil return nil
} }
private func attendingStatusForUser(_ event: EKEvent) -> EKParticipantStatus { private func attendingStatusForUser(_ event: EKEvent) -> EKParticipantStatus {
// First check if the current user is the organizer // First check if the current user is the organizer
if event.organizer?.isCurrentUser == true { if event.organizer?.isCurrentUser == true {
return event.organizer?.participantStatus ?? .unknown return event.organizer?.participantStatus ?? .unknown
} }
guard let attendes = event.attendees else { guard let attendes = event.attendees else {
return .unknown return .unknown
} }
for attende in attendes where attende.isCurrentUser { for attende in attendes where attende.isCurrentUser {
return attende.participantStatus return attende.participantStatus
} }
return .unknown return .unknown
} }
} }
@ -482,11 +481,11 @@ struct EventInfo {
let isSingleDay: Bool let isSingleDay: Bool
let meetingURL: URL? let meetingURL: URL?
let attendeStatus: EKParticipantStatus let attendeStatus: EKParticipantStatus
func metadataForMeeting() -> String { func metadataForMeeting() -> String {
let timeIntervalSinceNowForMeeting = event.startDate.timeIntervalSinceNow let timeIntervalSinceNowForMeeting = event.startDate.timeIntervalSinceNow
if (timeIntervalSinceNowForMeeting < 0 && timeIntervalSinceNowForMeeting > -300) { if timeIntervalSinceNowForMeeting < 0, timeIntervalSinceNowForMeeting > -300 {
return "started \(event.startDate.shortTimeAgoSinceNow) ago." return "started \(event.startDate.shortTimeAgoSinceNow) ago."
} else { } else {
let timeSince = Date().timeAgo(since: event.startDate) let timeSince = Date().timeAgo(since: event.startDate)
let withoutAn = timeSince.replacingOccurrences(of: "an", with: CLEmptyString) let withoutAn = timeSince.replacingOccurrences(of: "an", with: CLEmptyString)

3
Clocker/Events and Reminders/RemindersHandler.swift

@ -51,8 +51,7 @@ 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() {

6
Clocker/Menu Bar/StatusContainerView.swift

@ -31,12 +31,10 @@ 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
} }

2
Clocker/Menu Bar/StatusItemHandler.swift

@ -185,7 +185,7 @@ class StatusItemHandler: NSObject {
if let strongSelf = self { if let strongSelf = self {
strongSelf.performTimerWork() strongSelf.performTimerWork()
} }
}) })
// Tolerance, even a small amount, has a positive imapct on the power usage. As a rule, we set it to 10% of the interval // Tolerance, even a small amount, has a positive imapct on the power usage. As a rule, we set it to 10% of the interval
menubarTimer?.tolerance = shouldDisplaySeconds ? 0.5 : 20 menubarTimer?.tolerance = shouldDisplaySeconds ? 0.5 : 20

12
Clocker/Onboarding/OnboardingSearchController.swift

@ -27,8 +27,8 @@ class OnboardingSearchController: NSViewController {
private var geocodingKey: String = { private var geocodingKey: String = {
guard let path = Bundle.main.path(forResource: "Keys", ofType: "plist"), guard let path = Bundle.main.path(forResource: "Keys", ofType: "plist"),
let dictionary = NSDictionary(contentsOfFile: path), let dictionary = NSDictionary(contentsOfFile: path),
let apiKey = dictionary["GeocodingKey"] as? String let apiKey = dictionary["GeocodingKey"] as? String
else { else {
assertionFailure("Unable to find the API key") assertionFailure("Unable to find the API key")
return "" return ""
@ -61,7 +61,7 @@ class OnboardingSearchController: NSViewController {
resultsTableView.reloadData() resultsTableView.reloadData()
func setupUndoButton() { func setupUndoButton() {
let font = NSFont(name: "Avenir", size: 13) ?? NSFont.systemFont(ofSize: 13) let font = NSFont(name: "Avenir", size: 13) ?? NSFont.systemFont(ofSize: 13)
let attributes = [NSAttributedString.Key.foregroundColor: NSColor.linkColor, let attributes = [NSAttributedString.Key.foregroundColor: NSColor.linkColor,
NSAttributedString.Key.font: font] NSAttributedString.Key.font: font]
undoButton.attributedTitle = NSAttributedString(string: "UNDO", attributes: attributes) undoButton.attributedTitle = NSAttributedString(string: "UNDO", attributes: attributes)
@ -375,7 +375,7 @@ class OnboardingSearchController: NSViewController {
self.findLocalSearchResultsForTimezones() self.findLocalSearchResultsForTimezones()
self.prepareUIForPresentingResults() self.prepareUIForPresentingResults()
} }
}) })
} }
private func presentErrorMessage(_ errorMessage: String) { private func presentErrorMessage(_ errorMessage: String) {
@ -516,8 +516,8 @@ extension OnboardingSearchController: NSSearchFieldDelegate {
// return true if the action was handled; otherwise false // return true if the action was handled; otherwise false
return false return false
} }
func searchFieldDidEndSearching(_ sender: NSSearchField) { func searchFieldDidEndSearching(_ sender: NSSearchField) {
self.search(sender) search(sender)
} }
} }

19
Clocker/Overall App/ConfigExport.swift

@ -1,10 +1,9 @@
// Copyright © 2015 Abhishek Banthia // Copyright © 2015 Abhishek Banthia
import Foundation
import CoreModelKit import CoreModelKit
import Foundation
struct ConfigExport { struct ConfigExport {
private func generateJSONFromDefaults() { private func generateJSONFromDefaults() {
let selectedKeys: Set<String> = Set([ let selectedKeys: Set<String> = Set([
CLShowOnboardingFlow, CLShowOnboardingFlow,
@ -30,17 +29,17 @@ 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] = [:]
for (key, value) in dictionaryRep { for (key, value) in dictionaryRep {
if selectedKeys.contains(key) { if selectedKeys.contains(key) {
print("Key is \(key) and value is \(value)") print("Key is \(key) and value is \(value)")
clockerPrefs[key] = value clockerPrefs[key] = value
} }
} }
do { do {
let decodeJSON: [[String: Any]] = DataStore.shared().timezones().compactMap { data -> [String: Any]? in let decodeJSON: [[String: Any]] = DataStore.shared().timezones().compactMap { data -> [String: Any]? in
guard let customObject = TimezoneData.customObject(from: data) else { return nil } guard let customObject = TimezoneData.customObject(from: data) else { return nil }
@ -58,10 +57,10 @@ struct ConfigExport {
] ]
return timezoneDictionary return timezoneDictionary
} }
let timezoneDict = ["Timezones": decodeJSON] let timezoneDict = ["Timezones": decodeJSON]
clockerPrefs.merge(timezoneDict) { (current, _) in current} clockerPrefs.merge(timezoneDict) { current, _ in current }
guard let documentDirectoryUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } guard let documentDirectoryUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileUrl = documentDirectoryUrl.appendingPathComponent("Persons.json") let fileUrl = documentDirectoryUrl.appendingPathComponent("Persons.json")
// Transform array into data and save it into file // Transform array into data and save it into file
@ -71,13 +70,11 @@ struct ConfigExport {
} catch { } catch {
print(error) print(error)
} }
let json = try JSONSerialization.data(withJSONObject: clockerPrefs, options: .prettyPrinted) let json = try JSONSerialization.data(withJSONObject: clockerPrefs, options: .prettyPrinted)
print(json) print(json)
} catch { } catch {
print("Failure Observed \(error.localizedDescription)") print("Failure Observed \(error.localizedDescription)")
} }
} }
} }

2
Clocker/Overall App/NetworkManager.swift

@ -41,7 +41,7 @@ extension NetworkManager {
let session = URLSession(configuration: configuration) let session = URLSession(configuration: configuration)
guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string: encodedPath) let url = URL(string: encodedPath)
else { else {
completionHandler(nil, unableToGenerateURL) completionHandler(nil, unableToGenerateURL)
return nil return nil

24
Clocker/Overall App/Themer.swift

@ -149,7 +149,7 @@ extension Themer {
} }
return .light return .light
} }
func mainTextColor() -> NSColor { func mainTextColor() -> NSColor {
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
@ -210,8 +210,8 @@ extension Themer {
return return
themeIndex == .light themeIndex == .light
? NSImage(named: NSImage.Name("Settings"))! ? NSImage(named: NSImage.Name("Settings"))!
: NSImage(named: NSImage.Name("Settings-White"))! : NSImage(named: NSImage.Name("Settings-White"))!
} }
func pinImage() -> NSImage { func pinImage() -> NSImage {
@ -277,7 +277,7 @@ extension Themer {
if let symbolImage = symbolImage(for: "xmark") { if let symbolImage = symbolImage(for: "xmark") {
return symbolImage return symbolImage
} }
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
case .light, .solarizedLight: case .light, .solarizedLight:
@ -411,7 +411,7 @@ extension Themer {
if let privacyTabSFImage = symbolImage(for: "lock") { if let privacyTabSFImage = symbolImage(for: "lock") {
return privacyTabSFImage return privacyTabSFImage
} }
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
case .light, .solarizedLight: case .light, .solarizedLight:
@ -430,7 +430,7 @@ extension Themer {
if let appearanceTabImage = symbolImage(for: "eye") { if let appearanceTabImage = symbolImage(for: "eye") {
return appearanceTabImage return appearanceTabImage
} }
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
case .light, .solarizedLight: case .light, .solarizedLight:
@ -449,7 +449,7 @@ extension Themer {
if let calendarTabImage = symbolImage(for: "calendar") { if let calendarTabImage = symbolImage(for: "calendar") {
return calendarTabImage return calendarTabImage
} }
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
switch themeIndex { switch themeIndex {
case .light, .solarizedLight: case .light, .solarizedLight:
@ -463,11 +463,11 @@ extension Themer {
return themeIndex == .light ? NSImage(named: NSImage.Name("Calendar Tab Icon"))! : NSImage(named: NSImage.Name("Calendar Tab Dark"))! return themeIndex == .light ? NSImage(named: NSImage.Name("Calendar Tab Icon"))! : NSImage(named: NSImage.Name("Calendar Tab Dark"))!
} }
func generalTabImage() -> NSImage? { func generalTabImage() -> NSImage? {
return symbolImage(for: "gearshape") return symbolImage(for: "gearshape")
} }
func aboutTabImage() -> NSImage? { func aboutTabImage() -> NSImage? {
return symbolImage(for: "info.circle") return symbolImage(for: "info.circle")
} }
@ -501,16 +501,16 @@ extension Themer {
return nil return nil
} }
} }
func filledTrashImage() -> NSImage? { func filledTrashImage() -> NSImage? {
return symbolImage(for: "trash.fill") return symbolImage(for: "trash.fill")
} }
// Modern Slider // Modern Slider
func goBackwardsImage() -> NSImage? { func goBackwardsImage() -> NSImage? {
return symbolImage(for: "gobackward.15") return symbolImage(for: "gobackward.15")
} }
func goForwardsImage() -> NSImage? { func goForwardsImage() -> NSImage? {
return symbolImage(for: "goforward.15") return symbolImage(for: "goforward.15")
} }

2
Clocker/Panel/Data Layer/TimezoneDataOperations.swift

@ -368,7 +368,7 @@ extension TimezoneDataOperations {
to: Date()) to: Date())
guard let lat = dataObject.latitude, guard let lat = dataObject.latitude,
let long = dataObject.longitude let long = dataObject.longitude
else { else {
assertionFailure("Data was unexpectedly nil.") assertionFailure("Data was unexpectedly nil.")
return return

8
Clocker/Panel/Notes Popover/NotesPopover.swift

@ -224,7 +224,7 @@ class NotesPopover: NSViewController {
} }
completionHandler(completedDate) completionHandler(completedDate)
}) })
} catch { } catch {
assertionFailure("Failed to successfully initialize DataDetector") assertionFailure("Failed to successfully initialize DataDetector")
completionHandler(nil) completionHandler(nil)
@ -322,8 +322,7 @@ 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] = []
@ -392,8 +391,7 @@ 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()
} }
} }

23
Clocker/Panel/PanelController.swift

@ -153,8 +153,7 @@ 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
@ -186,16 +185,16 @@ class PanelController: ParentPanelController {
let preferences = DataStore.shared().timezones() let preferences = DataStore.shared().timezones()
guard let theme = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber, guard let theme = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber,
let displayFutureSliderKey = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber, let displayFutureSliderKey = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber,
let showAppInForeground = DataStore.shared().retrieve(key: CLShowAppInForeground) as? NSNumber, let showAppInForeground = DataStore.shared().retrieve(key: CLShowAppInForeground) as? NSNumber,
let relativeDateKey = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber, let relativeDateKey = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber,
let fontSize = DataStore.shared().retrieve(key: CLUserFontSizePreference) as? NSNumber, let fontSize = DataStore.shared().retrieve(key: CLUserFontSizePreference) as? NSNumber,
let sunriseTime = DataStore.shared().retrieve(key: CLSunriseSunsetTime) as? NSNumber, let sunriseTime = DataStore.shared().retrieve(key: CLSunriseSunsetTime) as? NSNumber,
let showDayInMenu = DataStore.shared().retrieve(key: CLShowDayInMenu) as? NSNumber, let showDayInMenu = DataStore.shared().retrieve(key: CLShowDayInMenu) as? NSNumber,
let showDateInMenu = DataStore.shared().retrieve(key: CLShowDateInMenu) as? NSNumber, let showDateInMenu = DataStore.shared().retrieve(key: CLShowDateInMenu) as? NSNumber,
let showPlaceInMenu = DataStore.shared().retrieve(key: CLShowPlaceInMenu) as? NSNumber, let showPlaceInMenu = DataStore.shared().retrieve(key: CLShowPlaceInMenu) as? NSNumber,
let showUpcomingEventView = DataStore.shared().retrieve(key: CLShowUpcomingEventView) as? String, let showUpcomingEventView = DataStore.shared().retrieve(key: CLShowUpcomingEventView) as? String,
let country = Locale.autoupdatingCurrent.regionCode let country = Locale.autoupdatingCurrent.regionCode
else { else {
return return
} }

10
Clocker/Panel/ParentPanelController+ModernSlider.swift

@ -20,13 +20,13 @@ extension ParentPanelController {
if modernSlider != nil { if modernSlider != nil {
goBackwardsButton.image = Themer.shared().goBackwardsImage() goBackwardsButton.image = Themer.shared().goBackwardsImage()
goForwardButton.image = Themer.shared().goForwardsImage() goForwardButton.image = Themer.shared().goForwardsImage()
goForwardButton.isContinuous = true goForwardButton.isContinuous = true
goBackwardsButton.isContinuous = true goBackwardsButton.isContinuous = true
goBackwardsButton.toolTip = "Navigate 15 mins back" goBackwardsButton.toolTip = "Navigate 15 mins back"
goForwardButton.toolTip = "Navigate 15 mins forward" goForwardButton.toolTip = "Navigate 15 mins forward"
modernSlider.enclosingScrollView?.scrollerInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) modernSlider.enclosingScrollView?.scrollerInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
modernSlider.enclosingScrollView?.backgroundColor = NSColor.clear modernSlider.enclosingScrollView?.backgroundColor = NSColor.clear
modernSlider.setAccessibility("ModernSlider") modernSlider.setAccessibility("ModernSlider")
@ -35,13 +35,13 @@ extension ParentPanelController {
selector: #selector(collectionViewDidScroll(_:)), selector: #selector(collectionViewDidScroll(_:)),
name: NSView.boundsDidChangeNotification, name: NSView.boundsDidChangeNotification,
object: modernSlider.superview) object: modernSlider.superview)
// Set the modern slider label! // Set the modern slider label!
closestQuarterTimeRepresentation = findClosestQuarterTimeApproximation() closestQuarterTimeRepresentation = findClosestQuarterTimeApproximation()
if let unwrappedClosetQuarterTime = closestQuarterTimeRepresentation { if let unwrappedClosetQuarterTime = closestQuarterTimeRepresentation {
modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(unwrappedClosetQuarterTime) modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(unwrappedClosetQuarterTime)
} }
// Make sure modern slider is centered horizontally! // Make sure modern slider is centered horizontally!
let indexPaths: Set<IndexPath> = Set([IndexPath(item: modernSlider.numberOfItems(inSection: 0) / 2, section: 0)]) let indexPaths: Set<IndexPath> = Set([IndexPath(item: modernSlider.numberOfItems(inSection: 0) / 2, section: 0)])
modernSlider.scrollToItems(at: indexPaths, scrollPosition: .centeredHorizontally) modernSlider.scrollToItems(at: indexPaths, scrollPosition: .centeredHorizontally)

96
Clocker/Panel/ParentPanelController.swift

@ -95,7 +95,7 @@ class ParentPanelController: NSWindowController {
@IBOutlet var modernContainerView: ModernSliderContainerView! @IBOutlet var modernContainerView: ModernSliderContainerView!
@IBOutlet var goBackwardsButton: NSButton! @IBOutlet var goBackwardsButton: NSButton!
@IBOutlet var goForwardButton: NSButton! @IBOutlet var goForwardButton: NSButton!
// Upcoming Events // Upcoming Events
@IBOutlet var upcomingEventCollectionView: NSCollectionView! @IBOutlet var upcomingEventCollectionView: NSCollectionView!
@IBOutlet var upcomingEventContainerView: NSView! @IBOutlet var upcomingEventContainerView: NSView!
@ -433,9 +433,8 @@ class ParentPanelController: NSWindowController {
if let note = object?.note, note.isEmpty == false { if let note = object?.note, note.isEmpty == false {
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
} }
} }
@ -495,21 +494,19 @@ class ParentPanelController: NSWindowController {
scrollViewHeight.constant = (screenHeight() - 100) scrollViewHeight.constant = (screenHeight() - 100)
} }
} }
if DataStore.shared().shouldDisplay(.futureSlider) {
let isModernSliderDisplayed = DataStore.shared().retrieve(key: CLDisplayFutureSliderKey) as? NSNumber ?? 0
if isModernSliderDisplayed == 0 {
if scrollViewHeight.constant >= (screenHeight() - 200) {
scrollViewHeight.constant = (screenHeight() - 300)
}
} else {
if scrollViewHeight.constant >= (screenHeight() - 200) {
scrollViewHeight.constant = (screenHeight() - 200)
}
}
} if DataStore.shared().shouldDisplay(.futureSlider) {
let isModernSliderDisplayed = DataStore.shared().retrieve(key: CLDisplayFutureSliderKey) as? NSNumber ?? 0
if isModernSliderDisplayed == 0 {
if scrollViewHeight.constant >= (screenHeight() - 200) {
scrollViewHeight.constant = (screenHeight() - 300)
}
} else {
if scrollViewHeight.constant >= (screenHeight() - 200) {
scrollViewHeight.constant = (screenHeight() - 200)
}
}
}
} }
func updateDefaultPreferences() { func updateDefaultPreferences() {
@ -624,9 +621,8 @@ class ParentPanelController: NSWindowController {
let current = preferences[$0] let current = preferences[$0]
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
} }
@ -646,8 +642,7 @@ 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
@ -723,26 +718,26 @@ class ParentPanelController: NSWindowController {
} }
@IBAction func dismissNextEventLabel(_: NSButton) { @IBAction func dismissNextEventLabel(_: NSButton) {
let eventCenter = EventCenter.sharedCenter() let eventCenter = EventCenter.sharedCenter()
let now = Date() let now = Date()
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 {
if let upcomingEvent = eventCenter.nextOccuring(events), let meetingLink = upcomingEvent.meetingURL { if let upcomingEvent = eventCenter.nextOccuring(events), let meetingLink = upcomingEvent.meetingURL {
NSWorkspace.shared.open(meetingLink) NSWorkspace.shared.open(meetingLink)
} }
} else { } else {
removeUpcomingEventView() removeUpcomingEventView()
} }
} }
func removeUpcomingEventView() { func removeUpcomingEventView() {
OperationQueue.main.addOperation { OperationQueue.main.addOperation {
if self.upcomingEventCollectionView != nil { if self.upcomingEventCollectionView != nil {
if self.stackView.arrangedSubviews.contains(self.upcomingEventContainerView!), self.upcomingEventContainerView?.isHidden == false { if self.stackView.arrangedSubviews.contains(self.upcomingEventContainerView!), self.upcomingEventContainerView?.isHidden == false {
self.upcomingEventContainerView?.isHidden = true self.upcomingEventContainerView?.isHidden = true
UserDefaults.standard.set("NO", forKey: CLShowUpcomingEventView) UserDefaults.standard.set("NO", forKey: CLShowUpcomingEventView)
Logger.log(object: ["Removed": "YES"], for: "Removed Upcoming Event View") Logger.log(object: ["Removed": "YES"], for: "Removed Upcoming Event View")
} }
} else if self.stackView.arrangedSubviews.contains(self.upcomingEventView!), self.upcomingEventView?.isHidden == false { } else if self.stackView.arrangedSubviews.contains(self.upcomingEventView!), self.upcomingEventView?.isHidden == false {
self.upcomingEventView?.isHidden = true self.upcomingEventView?.isHidden = true
UserDefaults.standard.set("NO", forKey: CLShowUpcomingEventView) UserDefaults.standard.set("NO", forKey: CLShowUpcomingEventView)
Logger.log(object: ["Removed": "YES"], for: "Removed Upcoming Event View") Logger.log(object: ["Removed": "YES"], for: "Removed Upcoming Event View")
@ -752,8 +747,7 @@ class ParentPanelController: NSWindowController {
@IBAction func calendarButtonAction(_: NSButton) { @IBAction func calendarButtonAction(_: NSButton) {
if calendarButton.title == NSLocalizedString("Click here to start.", if calendarButton.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()
@ -844,13 +838,12 @@ 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
} }
guard let upcomingEvent = eventCenter.nextOccuring(events) else { guard let upcomingEvent = eventCenter.nextOccuring(events) else {
self.setPlaceholdersForUpcomingCalendarView() self.setPlaceholdersForUpcomingCalendarView()
if #available(OSX 10.14, *) { if #available(OSX 10.14, *) {
@ -882,12 +875,12 @@ class ParentPanelController: NSWindowController {
} }
} }
} else { } else {
if self.upcomingEventCollectionView != nil { if upcomingEventCollectionView != nil {
self.upcomingEventsDataSource.updateEventsDataSource([]) upcomingEventsDataSource.updateEventsDataSource([])
self.upcomingEventCollectionView.reloadData() upcomingEventCollectionView.reloadData()
return return
} }
setPlaceholdersForUpcomingCalendarView() setPlaceholdersForUpcomingCalendarView()
if #available(OSX 10.14, *) { if #available(OSX 10.14, *) {
PerfLogger.endMarker("Fetch Calendar Events") PerfLogger.endMarker("Fetch Calendar Events")
@ -1071,7 +1064,7 @@ class ParentPanelController: NSWindowController {
@objc func openCrowdin() { @objc func openCrowdin() {
guard let localizationURL = URL(string: AboutUsConstants.CrowdInLocalizationLink), guard let localizationURL = URL(string: AboutUsConstants.CrowdInLocalizationLink),
let languageCode = Locale.preferredLanguages.first else { return } let languageCode = Locale.preferredLanguages.first else { return }
NSWorkspace.shared.open(localizationURL) NSWorkspace.shared.open(localizationURL)
@ -1148,14 +1141,13 @@ extension ParentPanelController: NSSharingServicePickerDelegate {
newProposedServices.append(contentsOf: filteredServices) newProposedServices.append(contentsOf: filteredServices)
return newProposedServices return newProposedServices
} }
private func retrieveAllTimes() -> String { private func retrieveAllTimes() -> String {
var clipboardCopy = String() var clipboardCopy = String()
let timezones = DataStore.shared().timezones() let timezones = DataStore.shared().timezones()
stride(from: 0, to: timezones.count, by: 1).forEach { stride(from: 0, to: timezones.count, by: 1).forEach {
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 {
{
clipboardCopy.append("\(cellView.customName.stringValue) - \(cellView.time.stringValue)\n") clipboardCopy.append("\(cellView.customName.stringValue) - \(cellView.time.stringValue)\n")
} }
} }

4
Clocker/Panel/Rate Controller/ReviewController.swift

@ -42,12 +42,12 @@ final class ReviewController {
// Check if the app has been installed for atleast 7 days // Check if the app has been installed for atleast 7 days
guard let install = storage.object(forKey: Keys.install) as? Date, guard let install = storage.object(forKey: Keys.install) as? Date,
install.timeIntervalSinceNow < minInstall install.timeIntervalSinceNow < minInstall
else { return false } else { return false }
// If we have never been prompted before, go ahead and prompt // If we have never been prompted before, go ahead and prompt
guard let lastPrompt = storage.object(forKey: Keys.lastPrompt) as? Date, guard let lastPrompt = storage.object(forKey: Keys.lastPrompt) as? Date,
let lastVersion = storage.object(forKey: Keys.lastVersion) as? String let lastVersion = storage.object(forKey: Keys.lastVersion) as? String
else { return true } else { return true }
// Minimum interval between two versions should be 45 // Minimum interval between two versions should be 45

6
Clocker/Panel/UI/TimezoneCellView.swift

@ -39,7 +39,7 @@ class TimezoneCellView: NSTableCellView {
func setupLayout() { func setupLayout() {
guard let relativeFont = relativeDate.font, guard let relativeFont = relativeDate.font,
let sunriseFont = sunriseSetTime.font let sunriseFont = sunriseSetTime.font
else { else {
assertionFailure("Unable to convert to NSString") assertionFailure("Unable to convert to NSString")
return return
@ -128,7 +128,7 @@ class TimezoneCellView: NSTableCellView {
} }
guard let customFont = customName.font, guard let customFont = customName.font,
let timeFont = time.font let timeFont = time.font
else { else {
assertionFailure("User Font Size is in unexpectedly nil") assertionFailure("User Font Size is in unexpectedly nil")
return return
@ -165,7 +165,7 @@ class TimezoneCellView: NSTableCellView {
} }
guard let panelTableView = searchView as? PanelTableView, guard let panelTableView = searchView as? PanelTableView,
let enclosingScroller = panelTableView.enclosingScrollView let enclosingScroller = panelTableView.enclosingScrollView
else { else {
// We might be coming from the preview tableview! // We might be coming from the preview tableview!
return return

2
Clocker/Panel/UI/TimezoneDataSource.swift

@ -144,7 +144,7 @@ extension TimezoneDataSource: NSTableViewDataSource, NSTableViewDelegate {
panelController.deleteTimezone(at: row) panelController.deleteTimezone(at: row)
} }
}) })
if #available(OSX 11.0, *) { if #available(OSX 11.0, *) {
swipeToDelete.image = Themer.shared().filledTrashImage() swipeToDelete.image = Themer.shared().filledTrashImage()

22
Clocker/Panel/Upcoming Events/ParentPanelController+UpcomingEvents.swift

@ -10,15 +10,15 @@ var avenirLightFont: NSFont {
} }
protocol UpcomingEventPanelDelegate: AnyObject { protocol UpcomingEventPanelDelegate: AnyObject {
func didRemoveCalendarView() func didRemoveCalendarView()
func didClickSupplementaryButton(_ sender: NSButton) func didClickSupplementaryButton(_ sender: NSButton)
} }
extension ParentPanelController { extension ParentPanelController {
func setupUpcomingEventViewCollectionViewIfNeccesary() { func setupUpcomingEventViewCollectionViewIfNeccesary() {
if upcomingEventCollectionView != nil { if upcomingEventCollectionView != nil {
upcomingEventsDataSource = UpcomingEventsDataSource(self) upcomingEventsDataSource = UpcomingEventsDataSource(self)
upcomingEventCollectionView.enclosingScrollView?.scrollerInsets = NSEdgeInsetsZero upcomingEventCollectionView.enclosingScrollView?.scrollerInsets = NSEdgeInsetsZero
upcomingEventCollectionView.enclosingScrollView?.backgroundColor = NSColor.clear upcomingEventCollectionView.enclosingScrollView?.backgroundColor = NSColor.clear
upcomingEventCollectionView.setAccessibility("UpcomingEventCollectionView") upcomingEventCollectionView.setAccessibility("UpcomingEventCollectionView")
upcomingEventCollectionView.dataSource = upcomingEventsDataSource upcomingEventCollectionView.dataSource = upcomingEventsDataSource
@ -28,11 +28,11 @@ extension ParentPanelController {
} }
extension ParentPanelController: UpcomingEventPanelDelegate { extension ParentPanelController: UpcomingEventPanelDelegate {
func didRemoveCalendarView() { func didRemoveCalendarView() {
removeUpcomingEventView() removeUpcomingEventView()
} }
func didClickSupplementaryButton(_ sender: NSButton) { func didClickSupplementaryButton(_ sender: NSButton) {
calendarButtonAction(sender) calendarButtonAction(sender)
} }
} }

10
Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift

@ -4,13 +4,13 @@ import Foundation
class UpcomingEventViewItem: NSCollectionViewItem { class UpcomingEventViewItem: NSCollectionViewItem {
static let reuseIdentifier = NSUserInterfaceItemIdentifier("UpcomingEventViewItem") static let reuseIdentifier = NSUserInterfaceItemIdentifier("UpcomingEventViewItem")
@IBOutlet var calendarColorView: NSView! @IBOutlet var calendarColorView: NSView!
@IBOutlet var leadingConstraint: NSLayoutConstraint! @IBOutlet var leadingConstraint: NSLayoutConstraint!
@IBOutlet var eventTitleLabel: NSTextField! @IBOutlet var eventTitleLabel: NSTextField!
@IBOutlet var eventSubtitleButton: NSButton! @IBOutlet var eventSubtitleButton: NSButton!
@IBOutlet var zoomButton: NSButton! @IBOutlet var zoomButton: NSButton!
private var meetingLink: URL? private var meetingLink: URL?
private weak var panelDelegate: UpcomingEventPanelDelegate? private weak var panelDelegate: UpcomingEventPanelDelegate?
@ -39,7 +39,7 @@ class UpcomingEventViewItem: NSCollectionViewItem {
} }
} }
func setupUndeterminedState(_ delegate: UpcomingEventPanelDelegate?) { func setupUndeterminedState(_ delegate: UpcomingEventPanelDelegate?) {
if leadingConstraint.constant != 10 { if leadingConstraint.constant != 10 {
leadingConstraint.constant = 10 leadingConstraint.constant = 10
} }
@ -70,14 +70,14 @@ class UpcomingEventViewItem: NSCollectionViewItem {
} }
@IBAction func calendarButtonAction(_ sender: NSButton) { @IBAction func calendarButtonAction(_ sender: NSButton) {
panelDelegate?.didClickSupplementaryButton(sender) panelDelegate?.didClickSupplementaryButton(sender)
} }
@objc func zoomButtonAction(_: Any) { @objc func zoomButtonAction(_: Any) {
if let meetingURL = meetingLink { if let meetingURL = meetingLink {
NSWorkspace.shared.open(meetingURL) NSWorkspace.shared.open(meetingURL)
} else { } else {
panelDelegate?.didRemoveCalendarView() panelDelegate?.didRemoveCalendarView()
} }
} }
} }

12
Clocker/Panel/Upcoming Events/UpcomingEventsDataSource.swift

@ -4,12 +4,12 @@ import Foundation
class UpcomingEventsDataSource: NSObject, NSCollectionViewDataSource, NSCollectionViewDelegateFlowLayout { class UpcomingEventsDataSource: NSObject, NSCollectionViewDataSource, NSCollectionViewDelegateFlowLayout {
private var upcomingEvents: [EventInfo] = [] private var upcomingEvents: [EventInfo] = []
private weak var delegate: UpcomingEventPanelDelegate? private weak var delegate: UpcomingEventPanelDelegate?
init(_ panelDelegate: UpcomingEventPanelDelegate?) { init(_ panelDelegate: UpcomingEventPanelDelegate?) {
super.init() super.init()
delegate = panelDelegate delegate = panelDelegate
} }
func updateEventsDataSource(_ events: [EventInfo]) { func updateEventsDataSource(_ events: [EventInfo]) {
upcomingEvents = events upcomingEvents = events

6
Clocker/Preferences/About/AboutViewController.swift

@ -98,7 +98,7 @@ class AboutViewController: ParentViewController {
@IBAction func openMyTwitter(_: Any) { @IBAction func openMyTwitter(_: Any) {
guard let twitterURL = URL(string: AboutUsConstants.TwitterLink), guard let twitterURL = URL(string: AboutUsConstants.TwitterLink),
let countryCode = Locale.autoupdatingCurrent.regionCode else { return } let countryCode = Locale.autoupdatingCurrent.regionCode else { return }
NSWorkspace.shared.open(twitterURL) NSWorkspace.shared.open(twitterURL)
@ -109,7 +109,7 @@ class AboutViewController: ParentViewController {
@IBAction func viewSource(_: Any) { @IBAction func viewSource(_: Any) {
guard let sourceURL = URL(string: AboutUsConstants.AppStoreLink), guard let sourceURL = URL(string: AboutUsConstants.AppStoreLink),
let countryCode = Locale.autoupdatingCurrent.regionCode else { return } let countryCode = Locale.autoupdatingCurrent.regionCode else { return }
NSWorkspace.shared.open(sourceURL) NSWorkspace.shared.open(sourceURL)
@ -131,7 +131,7 @@ class AboutViewController: ParentViewController {
@IBAction func openGitHub(_: Any) { @IBAction func openGitHub(_: Any) {
guard let localizationURL = URL(string: AboutUsConstants.CrowdInLocalizationLink), guard let localizationURL = URL(string: AboutUsConstants.CrowdInLocalizationLink),
let languageCode = Locale.preferredLanguages.first else { return } let languageCode = Locale.preferredLanguages.first else { return }
NSWorkspace.shared.open(localizationURL) NSWorkspace.shared.open(localizationURL)

31
Clocker/Preferences/App Feedback/AppFeedbackWindowController.swift

@ -114,7 +114,7 @@ class AppFeedbackWindowController: NSWindowController {
let feedbackInfo = retrieveDataForSending() let feedbackInfo = retrieveDataForSending()
Logger.info("About to send \(feedbackInfo)") Logger.info("About to send \(feedbackInfo)")
sendDataToFirebase(feedbackInfo: feedbackInfo) sendDataToFirebase(feedbackInfo: feedbackInfo)
showSucccessOnSendingInfo() showSucccessOnSendingInfo()
} }
@ -127,30 +127,30 @@ class AppFeedbackWindowController: NSWindowController {
let cleanedUpString = feedbackTextView.string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) let cleanedUpString = feedbackTextView.string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if cleanedUpString.isEmpty { if cleanedUpString.isEmpty {
self.window?.contentView?.makeToast(AppFeedbackConstants.CLFeedbackNotEnteredErrorMessage) window?.contentView?.makeToast(AppFeedbackConstants.CLFeedbackNotEnteredErrorMessage)
isActivityInProgress = false isActivityInProgress = false
return false return false
} }
return true return true
} }
private func generateUserPreferences() -> String { private func generateUserPreferences() -> String {
let preferences = DataStore.shared().timezones() let preferences = DataStore.shared().timezones()
guard let theme = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber, guard let theme = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber,
let displayFutureSliderKey = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber, let displayFutureSliderKey = DataStore.shared().retrieve(key: CLThemeKey) as? NSNumber,
let relativeDateKey = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber, let relativeDateKey = DataStore.shared().retrieve(key: CLRelativeDateKey) as? NSNumber,
let country = Locale.autoupdatingCurrent.regionCode let country = Locale.autoupdatingCurrent.regionCode
else { else {
return "Error" return "Error"
} }
let selectedTimezones = preferences.compactMap { data -> String? in let selectedTimezones = preferences.compactMap { data -> String? in
guard let timezoneObject = TimezoneData.customObject(from: data) else { guard let timezoneObject = TimezoneData.customObject(from: data) else {
return nil return nil
} }
return "Timezone: \(timezoneObject.timezone()) Name: \(timezoneObject.formattedAddress ?? "No") Favourited: \((timezoneObject.isFavourite == 1) ? "Yes": "No") Note: \(timezoneObject.note ?? "No Note") System: \(timezoneObject.isSystemTimezone ? "Yes": "No")" return "Timezone: \(timezoneObject.timezone()) Name: \(timezoneObject.formattedAddress ?? "No") Favourited: \((timezoneObject.isFavourite == 1) ? "Yes" : "No") Note: \(timezoneObject.note ?? "No Note") System: \(timezoneObject.isSystemTimezone ? "Yes" : "No")"
} }
var relativeDate = "Relative" var relativeDate = "Relative"
@ -160,30 +160,29 @@ class AppFeedbackWindowController: NSWindowController {
} else if relativeDateKey.isEqual(to: NSNumber(value: 2)) { } else if relativeDateKey.isEqual(to: NSNumber(value: 2)) {
relativeDate = "Date" relativeDate = "Date"
} }
var themeInfo = "Light" var themeInfo = "Light"
if theme.isEqual(to: NSNumber(value: 1)) { if theme.isEqual(to: NSNumber(value: 1)) {
themeInfo = "Dark" themeInfo = "Dark"
} else if theme.isEqual(to: NSNumber(value: 2)) { } else if theme.isEqual(to: NSNumber(value: 2)) {
themeInfo = "System" themeInfo = "System"
} }
var futureSlider = "Modern" var futureSlider = "Modern"
if displayFutureSliderKey.isEqual(to: NSNumber(value: 1)) { if displayFutureSliderKey.isEqual(to: NSNumber(value: 1)) {
futureSlider = "Legacy" futureSlider = "Legacy"
} else if theme.isEqual(to: NSNumber(value: 2)) { } else if theme.isEqual(to: NSNumber(value: 2)) {
futureSlider = "Hidden" futureSlider = "Hidden"
} }
return """ return """
"Theme: \(themeInfo), "Display Future Slider": \(futureSlider), "Relative Date": \(relativeDate), "Country": \(country), "Timezones": \(selectedTimezones) "Theme: \(themeInfo), "Display Future Slider": \(futureSlider), "Relative Date": \(relativeDate), "Country": \(country), "Timezones": \(selectedTimezones)
""" """
} }
private func retrieveDataForSending() -> [String: String] { private func retrieveDataForSending() -> [String: String] {
guard let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String, guard let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String,
let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String
else { else {
return [:] return [:]
} }
@ -286,7 +285,7 @@ class AppFeedbackWindowController: NSWindowController {
@IBAction func navigateToSupportTwitter(_: Any) { @IBAction func navigateToSupportTwitter(_: Any) {
guard let twitterURL = URL(string: AboutUsConstants.TwitterLink), guard let twitterURL = URL(string: AboutUsConstants.TwitterLink),
let countryCode = Locale.autoupdatingCurrent.regionCode else { return } let countryCode = Locale.autoupdatingCurrent.regionCode else { return }
NSWorkspace.shared.open(twitterURL) NSWorkspace.shared.open(twitterURL)

18
Clocker/Preferences/Appearance/AppearanceViewController.swift

@ -62,10 +62,8 @@ class AppearanceViewController: ParentViewController {
"6 days", "6 days",
"7 days", "7 days",
]) ])
if #available(macOS 11.0, *) { if #available(macOS 11.0, *) {} else {
} else {
theme.font = NSFont.systemFont(ofSize: 13) theme.font = NSFont.systemFont(ofSize: 13)
} }
@ -126,8 +124,7 @@ class AppearanceViewController: ParentViewController {
sliderDayRangePopup.selectItem(at: selectedIndex.intValue) sliderDayRangePopup.selectItem(at: selectedIndex.intValue)
} }
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {} else {
} else {
theme.removeItem(at: 2) theme.removeItem(at: 2)
} }
@ -153,7 +150,7 @@ class AppearanceViewController: ParentViewController {
@IBOutlet var menubarModeLabel: NSTextField! @IBOutlet var menubarModeLabel: NSTextField!
@IBOutlet var previewLabel: NSTextField! @IBOutlet var previewLabel: NSTextField!
@IBOutlet var miscelleaneousLabel: NSTextField! @IBOutlet var miscelleaneousLabel: NSTextField!
@IBOutlet weak var dstTransitionField: NSTextField! @IBOutlet var dstTransitionField: NSTextField!
// Panel Preview // Panel Preview
@IBOutlet var previewPanelTableView: NSTableView! @IBOutlet var previewPanelTableView: NSTableView!
@ -180,8 +177,8 @@ class AppearanceViewController: ParentViewController {
previewLabel, miscelleaneousLabel, dstTransitionField].forEach { previewLabel, miscelleaneousLabel, dstTransitionField].forEach {
$0?.textColor = Themer.shared().mainTextColor() $0?.textColor = Themer.shared().mainTextColor()
} }
self.previewPanelTableView.backgroundColor = Themer.shared().mainBackgroundColor() previewPanelTableView.backgroundColor = Themer.shared().mainBackgroundColor()
} }
@IBAction func timeFormatSelectionChanged(_ sender: NSPopUpButton) { @IBAction func timeFormatSelectionChanged(_ sender: NSPopUpButton) {
@ -191,8 +188,7 @@ 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") {
{
print("Seconds are contained") print("Seconds are contained")
guard let panelController = PanelController.panel() else { return } guard let panelController = PanelController.panel() else { return }
panelController.pauseTimer() panelController.pauseTimer()

8
Clocker/Preferences/Calendar/CalendarViewController.swift

@ -215,7 +215,7 @@ class CalendarViewController: ParentViewController {
[headerLabel, upcomingEventView, allDayMeetingsLabel, [headerLabel, upcomingEventView, allDayMeetingsLabel,
showNextMeetingLabel, nextMeetingAccessoryLabel, truncateTextLabel, showNextMeetingLabel, nextMeetingAccessoryLabel, truncateTextLabel,
showEventsFromLabel, charactersField, truncateAccessoryLabel].forEach { $0?.textColor = Themer.shared().mainTextColor() } showEventsFromLabel, charactersField, truncateAccessoryLabel].forEach { $0?.textColor = Themer.shared().mainTextColor() }
calendarsTableView.backgroundColor = Themer.shared().mainBackgroundColor() calendarsTableView.backgroundColor = Themer.shared().mainBackgroundColor()
truncateTextField.backgroundColor = Themer.shared().mainBackgroundColor() truncateTextField.backgroundColor = Themer.shared().mainBackgroundColor()
} }
@ -243,15 +243,13 @@ 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,8 +104,7 @@ 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
} }
@ -164,7 +163,7 @@ extension PreferencesDataSource: NSTableViewDataSource {
"Old Label": dataObject.customLabel ?? "Error", "Old Label": dataObject.customLabel ?? "Error",
"New Label": formattedValue, "New Label": formattedValue,
], ],
for: "Custom Label Changed") for: "Custom Label Changed")
dataObject.setLabel(formattedValue) dataObject.setLabel(formattedValue)
@ -177,7 +176,7 @@ extension PreferencesDataSource: NSTableViewDataSource {
"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")
} }
} }

21
Clocker/Preferences/General/PreferencesViewController.swift

@ -42,8 +42,8 @@ class PreferencesViewController: ParentViewController {
private var geocodingKey: String = { private var geocodingKey: String = {
guard let path = Bundle.main.path(forResource: "Keys", ofType: "plist"), guard let path = Bundle.main.path(forResource: "Keys", ofType: "plist"),
let dictionary = NSDictionary(contentsOfFile: path), let dictionary = NSDictionary(contentsOfFile: path),
let apiKey = dictionary["GeocodingKey"] as? String let apiKey = dictionary["GeocodingKey"] as? String
else { else {
// assertionFailure("Unable to find the API key") // assertionFailure("Unable to find the API key")
return "" return ""
@ -338,10 +338,9 @@ extension PreferencesViewController: NSTableViewDataSource, NSTableViewDelegate
for: "favouriteRemoved") for: "favouriteRemoved")
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)
} }
@ -459,7 +458,7 @@ extension PreferencesViewController {
self.prepareUIForPresentingResults() self.prepareUIForPresentingResults()
} }
}) })
} }
} }
@ -884,7 +883,7 @@ extension PreferencesViewController {
let system = NSTimeZone.system let system = NSTimeZone.system
guard let object1 = TimezoneData.customObject(from: obj1), guard let object1 = TimezoneData.customObject(from: obj1),
let object2 = TimezoneData.customObject(from: obj2) let object2 = TimezoneData.customObject(from: obj2)
else { else {
assertionFailure("Data was unexpectedly nil") assertionFailure("Data was unexpectedly nil")
return false return false
@ -912,7 +911,7 @@ extension PreferencesViewController {
let sortedLabels = selectedTimeZones.sorted { obj1, obj2 -> Bool in let sortedLabels = selectedTimeZones.sorted { obj1, obj2 -> Bool in
guard let object1 = TimezoneData.customObject(from: obj1), guard let object1 = TimezoneData.customObject(from: obj1),
let object2 = TimezoneData.customObject(from: obj2) let object2 = TimezoneData.customObject(from: obj2)
else { else {
assertionFailure("Data was unexpectedly nil") assertionFailure("Data was unexpectedly nil")
return false return false
@ -936,7 +935,7 @@ extension PreferencesViewController {
let sortedByAddress = selectedTimeZones.sorted { obj1, obj2 -> Bool in let sortedByAddress = selectedTimeZones.sorted { obj1, obj2 -> Bool in
guard let object1 = TimezoneData.customObject(from: obj1), guard let object1 = TimezoneData.customObject(from: obj1),
let object2 = TimezoneData.customObject(from: obj2) let object2 = TimezoneData.customObject(from: obj2)
else { else {
assertionFailure("Data was unexpectedly nil") assertionFailure("Data was unexpectedly nil")
return false return false
@ -1003,7 +1002,7 @@ extension PreferencesViewController: PreferenceSelectionUpdates {
let sortedTimezones = selectedTimeZones.sorted { obj1, obj2 -> Bool in let sortedTimezones = selectedTimeZones.sorted { obj1, obj2 -> Bool in
guard let object1 = TimezoneData.customObject(from: obj1), guard let object1 = TimezoneData.customObject(from: obj1),
let object2 = TimezoneData.customObject(from: obj2) let object2 = TimezoneData.customObject(from: obj2)
else { else {
assertionFailure("Data was unexpectedly nil") assertionFailure("Data was unexpectedly nil")
return false return false

2
Clocker/Preferences/General/SearchDataSource.swift

@ -78,7 +78,7 @@ class SearchDataSource: NSObject {
if index >= filteredArray.count { if index >= filteredArray.count {
return nil return nil
} }
return filteredArray[index % filteredArray.count] return filteredArray[index % filteredArray.count]
} }

6
Clocker/Preferences/Menu Bar/StatusContainerView.swift

@ -33,12 +33,10 @@ 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
} }

2
Clocker/Preferences/Menu Bar/StatusItemHandler.swift

@ -188,7 +188,7 @@ class StatusItemHandler: NSObject {
if let strongSelf = self { if let strongSelf = self {
strongSelf.refresh() strongSelf.refresh()
} }
}) })
// Tolerance, even a small amount, has a positive imapct on the power usage. As a rule, we set it to 10% of the interval // Tolerance, even a small amount, has a positive imapct on the power usage. As a rule, we set it to 10% of the interval
menubarTimer?.tolerance = shouldDisplaySeconds ? 0.5 : 20 menubarTimer?.tolerance = shouldDisplaySeconds ? 0.5 : 20

15
Clocker/Preferences/Menu Bar/UpcomingEventStatusItemView.swift

@ -1,11 +1,11 @@
// Copyright © 2015 Abhishek Banthia // Copyright © 2015 Abhishek Banthia
import Foundation
import AppKit import AppKit
import Foundation
class UpcomingEventStatusItemView: NSView { class UpcomingEventStatusItemView: NSView {
static let containerWidth = 70 static let containerWidth = 70
private let nextEventField = NSTextField(labelWithString: "Next Event") private let nextEventField = NSTextField(labelWithString: "Next Event")
private let etaField = NSTextField(labelWithString: "5 mins") private let etaField = NSTextField(labelWithString: "5 mins")
var dataObject: EventInfo! { var dataObject: EventInfo! {
@ -13,6 +13,7 @@ class UpcomingEventStatusItemView: NSView {
initialSetup() initialSetup()
} }
} }
private var timeAttributes: [NSAttributedString.Key: AnyObject] { private var timeAttributes: [NSAttributedString.Key: AnyObject] {
let textColor = hasDarkAppearance ? NSColor.white : NSColor.black let textColor = hasDarkAppearance ? NSColor.white : NSColor.black
@ -36,7 +37,7 @@ class UpcomingEventStatusItemView: NSView {
] ]
return textFontAttributes return textFontAttributes
} }
override init(frame frameRect: NSRect) { override init(frame frameRect: NSRect) {
super.init(frame: frameRect) super.init(frame: frameRect)
@ -63,16 +64,16 @@ class UpcomingEventStatusItemView: NSView {
etaField.bottomAnchor.constraint(equalTo: bottomAnchor), etaField.bottomAnchor.constraint(equalTo: bottomAnchor),
]) ])
} }
required init?(coder: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
private func initialSetup() { private func initialSetup() {
nextEventField.attributedStringValue = NSAttributedString(string: "Next Event", attributes: textFontAttributes) nextEventField.attributedStringValue = NSAttributedString(string: "Next Event", attributes: textFontAttributes)
etaField.attributedStringValue = NSAttributedString(string: dataObject.metadataForMeeting(), attributes: timeAttributes) etaField.attributedStringValue = NSAttributedString(string: dataObject.metadataForMeeting(), attributes: timeAttributes)
} }
func updateWithNextEventInfo(_ metadata: String) { func updateWithNextEventInfo(_ metadata: String) {
nextEventField.attributedStringValue = NSAttributedString(string: "Next Event", attributes: textFontAttributes) nextEventField.attributedStringValue = NSAttributedString(string: "Next Event", attributes: textFontAttributes)
etaField.attributedStringValue = NSAttributedString(string: metadata, attributes: timeAttributes) etaField.attributedStringValue = NSAttributedString(string: metadata, attributes: timeAttributes)

4
Clocker/Preferences/OneWindowController.swift

@ -84,11 +84,11 @@ class OneWindowController: NSWindowController {
var identifierTOImageMapping: [String: NSImage] = ["Appearance Tab": themer.appearanceTabImage(), var identifierTOImageMapping: [String: NSImage] = ["Appearance Tab": themer.appearanceTabImage(),
"Calendar Tab": themer.calendarTabImage(), "Calendar Tab": themer.calendarTabImage(),
"Permissions Tab": themer.privacyTabImage()] "Permissions Tab": themer.privacyTabImage()]
if let prefsTabImage = themer.generalTabImage() { if let prefsTabImage = themer.generalTabImage() {
identifierTOImageMapping["Preferences Tab"] = prefsTabImage identifierTOImageMapping["Preferences Tab"] = prefsTabImage
} }
if let aboutTabImage = themer.aboutTabImage() { if let aboutTabImage = themer.aboutTabImage() {
identifierTOImageMapping["About Tab"] = aboutTabImage identifierTOImageMapping["About Tab"] = aboutTabImage
} }

Loading…
Cancel
Save