From 8a2148c3caa31979b722a970b8ef5d4a7c708990 Mon Sep 17 00:00:00 2001 From: Abhi Date: Sun, 19 Feb 2023 17:46:29 -0500 Subject: [PATCH 01/39] Fixing tests. --- Clocker/ClockerUITests/OnboardingTests.swift | 2 +- Clocker/ClockerUnitTests/ClockerUnitTests.swift | 8 ++++++-- Clocker/ClockerUnitTests/SearchDataSourceTests.swift | 4 +++- .../CoreModelKit/Sources/CoreModelKit/TimezoneData.swift | 8 ++++++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Clocker/ClockerUITests/OnboardingTests.swift b/Clocker/ClockerUITests/OnboardingTests.swift index f857f69..2dd73a2 100644 --- a/Clocker/ClockerUITests/OnboardingTests.swift +++ b/Clocker/ClockerUITests/OnboardingTests.swift @@ -2,7 +2,7 @@ import XCTest -let CLOnboaringTestsLaunchArgument = "isTestingTheOnboardingFlow" +let CLOnboardingTestsLaunchArgument = "isTestingTheOnboardingFlow" class OnboardingTests: XCTestCase { var app: XCUIApplication! diff --git a/Clocker/ClockerUnitTests/ClockerUnitTests.swift b/Clocker/ClockerUnitTests/ClockerUnitTests.swift index efc3a60..60d24c7 100644 --- a/Clocker/ClockerUnitTests/ClockerUnitTests.swift +++ b/Clocker/ClockerUnitTests/ClockerUnitTests.swift @@ -170,10 +170,14 @@ class ClockerUnitTests: XCTestCase { // The below test might fail outside California or if DST is active! // CI is calibrated to be on LA timezone! func testTimeDifference() { - XCTAssertTrue(operations.timeDifference() == ", 9h 30m ahead", "Difference was unexpectedly: \(operations.timeDifference())") + let observingDaylightSavings = TimeZone.autoupdatingCurrent.isDaylightSavingTime(for: Date()) + let expectedDifference = observingDaylightSavings ? ", 9h 30m ahead" : ", 10h 30m ahead" + let expectedDifferenceForAuckland = observingDaylightSavings ? ", 16h ahead" : ", 18h ahead" + + XCTAssertTrue(operations.timeDifference() == expectedDifference, "Difference was unexpectedly: \(operations.timeDifference())") XCTAssertTrue(californiaOperations.timeDifference() == ", 3h behind", "Difference was unexpectedly: \(californiaOperations.timeDifference())") XCTAssertTrue(floridaOperations.timeDifference() == "", "Difference was unexpectedly: \(floridaOperations.timeDifference())") - XCTAssertTrue(aucklandOperations.timeDifference() == ", 16h ahead", "Difference was unexpectedly: \(aucklandOperations.timeDifference())") + XCTAssertTrue(aucklandOperations.timeDifference() == expectedDifferenceForAuckland, "Difference was unexpectedly: \(aucklandOperations.timeDifference())") XCTAssertTrue(omahaOperations.timeDifference() == ", 1h behind", "Difference was unexpectedly: \(omahaOperations.timeDifference())") } diff --git a/Clocker/ClockerUnitTests/SearchDataSourceTests.swift b/Clocker/ClockerUnitTests/SearchDataSourceTests.swift index e4b0c1d..8b63253 100644 --- a/Clocker/ClockerUnitTests/SearchDataSourceTests.swift +++ b/Clocker/ClockerUnitTests/SearchDataSourceTests.swift @@ -106,7 +106,9 @@ class SearchDataSourceTests: XCTestCase { setupMockData() let result = subject.retrieveSelectedTimezone(0) - XCTAssert(result.timezone.abbreviation == "PDT") + let possibleOutcomes = Set(["PDT", "PST"]) + XCTAssert(possibleOutcomes.contains(result.timezone.abbreviation ?? "NA"), + "Result timezone is actually \(result.timezone.abbreviation ?? "NA")") } func testRetrieveSelectedTimezoneWithEmptySearchField() { diff --git a/Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift b/Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift index ec66b4c..d4bc693 100644 --- a/Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift +++ b/Clocker/CoreModelKit/Sources/CoreModelKit/TimezoneData.swift @@ -267,6 +267,14 @@ public class TimezoneData: NSObject, NSCoding { let formatInString = TimezoneData.values[key] ?? DateFormat.twelveHour return formatInString.contains("ss") } + + public func isDaylightSavings() -> Bool { + guard let timezone = TimeZone(abbreviation: timezone()) else { + return false + } + + return timezone.isDaylightSavingTime(for: Date()) + } override public var hash: Int { guard let placeIdentifier = placeID, let timezone = timezoneID else { From 080f9b45f076bc162f81400a373b0c82cdcf6423 Mon Sep 17 00:00:00 2001 From: Abhi Date: Sat, 22 Apr 2023 16:02:06 -0400 Subject: [PATCH 02/39] Quick fixes to scroller visibility for upcoming events view. --- Clocker/Clocker/en.lproj/Panel.xib | 8 ++++---- .../ParentPanelController+UpcomingEvents.swift | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Clocker/Clocker/en.lproj/Panel.xib b/Clocker/Clocker/en.lproj/Panel.xib index 7df3cdc..b42805c 100755 --- a/Clocker/Clocker/en.lproj/Panel.xib +++ b/Clocker/Clocker/en.lproj/Panel.xib @@ -1,8 +1,8 @@ - + - + @@ -43,7 +43,7 @@ - + @@ -533,7 +533,7 @@ - - - @@ -332,8 +371,12 @@ DQ + + + + + - diff --git a/Clocker/Onboarding/OnboardingPermissionsViewController.swift b/Clocker/Onboarding/OnboardingPermissionsViewController.swift index f321f04..03d53c2 100644 --- a/Clocker/Onboarding/OnboardingPermissionsViewController.swift +++ b/Clocker/Onboarding/OnboardingPermissionsViewController.swift @@ -6,6 +6,7 @@ import CoreLoggerKit class OnboardingPermissionsViewController: NSViewController { @IBOutlet var reminderGrantButton: NSButton! @IBOutlet var calendarGrantButton: NSButton! + @IBOutlet var locationGrantButton: NSButton! @IBOutlet var reminderView: NSView! @IBOutlet var calendarView: NSView! @@ -31,7 +32,7 @@ class OnboardingPermissionsViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - [calendarView, reminderView].forEach { $0?.applyShadow() } + [calendarView, reminderView, locationView].forEach { $0?.applyShadow() } setup() } @@ -52,23 +53,25 @@ class OnboardingPermissionsViewController: NSViewController { calendarHeaderLabel.stringValue = NSLocalizedString("Calendar Access Title", comment: "Title for Calendar access label") calendarDetailLabel.stringValue = "Calendar Detail".localized() - - privacyLabel.stringValue = CLEmptyString + + locationHeaderLabel.stringValue = "Location Access" + locationDetailLabel.stringValue = "Accurately track your local time; especially useful if you travel." [calendarHeaderLabel, calendarDetailLabel, privacyLabel, reminderDetailLabel, reminderHeaderLabel, onboardingTypeLabel, appLabel].forEach { $0?.textColor = Themer.shared().mainTextColor() } } private func setupButtons() { -// if LocationController.sharedInstance.locationAccessGranted() { -// locationButton.title = "Granted" -// } else if LocationController.sharedInstance.locationAccessDenied() { -// locationButton.title = "Denied" -// } else if LocationController.sharedInstance.locationAccessNotDetermined() { -// locationButton.title = "Grant" -// } else { -// locationButton.title = "Unexpected" -// } + let locationController = LocationController.shared() + if locationController.locationAccessGranted() { + locationGrantButton.title = "Granted" + } else if locationController.locationAccessDenied() { + locationGrantButton.title = "Denied" + } else if locationController.locationAccessNotDetermined() { + locationGrantButton.title = "Grant" + } else { + locationGrantButton.title = "Unexpected" + } if EventCenter.sharedCenter().calendarAccessGranted() { calendarGrantButton.title = "Granted".localized() @@ -153,4 +156,17 @@ class OnboardingPermissionsViewController: NSViewController { reminderGrantButton.title = "Denied".localized() } } + + @IBAction func locationAction(_: NSButton) { + let locationController = LocationController.shared() + if locationController.locationAccessNotDetermined() { + locationActivityIndicator.startAnimation(nil) + locationController.determineAndRequestLocationAuthorization() + } else if locationController.locationAccessDenied() { + locationGrantButton.title = "Denied".localized() + } else if locationController.locationAccessGranted() { + locationGrantButton.title = "Granted".localized() + } + + } } From f93959c92755c62a4a9f613325ac647408825cf2 Mon Sep 17 00:00:00 2001 From: Abhishek Banthia <8280282+n0shake@users.noreply.github.com> Date: Sat, 20 May 2023 16:57:45 -0400 Subject: [PATCH 35/39] Update Activity indicator if authorization status changes. --- Clocker/Clocker/LocationController.swift | 7 ++++ Clocker/Onboarding/Onboarding.storyboard | 4 +-- .../OnboardingPermissionsViewController.swift | 32 ++++++++++++++----- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Clocker/Clocker/LocationController.swift b/Clocker/Clocker/LocationController.swift index f31ffdd..3b43b9c 100644 --- a/Clocker/Clocker/LocationController.swift +++ b/Clocker/Clocker/LocationController.swift @@ -5,9 +5,14 @@ import CoreLocation import CoreLoggerKit import CoreModelKit +protocol LocationControllerDelegate: NSObject { + func didChangeAuthorizationStatus() +} + class LocationController: NSObject { private let store: DataStore private static var sharedController = LocationController(withStore: DataStore.shared()) + weak var delegate: LocationControllerDelegate? init(withStore dataStore: DataStore) { store = dataStore @@ -33,6 +38,7 @@ class LocationController: NSObject { } func locationAccessGranted() -> Bool { + print("Location Status is ", CLLocationManager.authorizationStatus().rawValue.description) return CLLocationManager.authorizationStatus() == .authorizedAlways || CLLocationManager.authorizationStatus() == .authorized } @@ -120,6 +126,7 @@ extension LocationController: CLLocationManagerDelegate { } else if status == .notDetermined || status == .authorized || status == .authorizedAlways { locationManager.startUpdatingLocation() } + delegate?.didChangeAuthorizationStatus() } func locationManager(_: CLLocationManager, didFailWithError error: Error) { diff --git a/Clocker/Onboarding/Onboarding.storyboard b/Clocker/Onboarding/Onboarding.storyboard index 659ce34..b854fdc 100644 --- a/Clocker/Onboarding/Onboarding.storyboard +++ b/Clocker/Onboarding/Onboarding.storyboard @@ -189,7 +189,7 @@ DQ - + @@ -201,7 +201,7 @@ DQ - + diff --git a/Clocker/Onboarding/OnboardingPermissionsViewController.swift b/Clocker/Onboarding/OnboardingPermissionsViewController.swift index 03d53c2..f7e8588 100644 --- a/Clocker/Onboarding/OnboardingPermissionsViewController.swift +++ b/Clocker/Onboarding/OnboardingPermissionsViewController.swift @@ -42,16 +42,13 @@ class OnboardingPermissionsViewController: NSViewController { } private func setup() { - appLabel.stringValue = NSLocalizedString("Permissions Tab", - comment: "Title for Permissions screen") + appLabel.stringValue = NSLocalizedString("Permissions Tab", comment: "Title for Permissions screen") onboardingTypeLabel.stringValue = "Your data doesn't leave your device 🔐" - reminderHeaderLabel.stringValue = NSLocalizedString("Reminders Access Title", - comment: "Title for Reminders Access Label") - reminderDetailLabel.stringValue = "Set reminders in the timezone of the location of your choice. Your reminders are stored in the default Reminders app. " + reminderHeaderLabel.stringValue = NSLocalizedString("Reminders Access Title",comment: "Title for Reminders Access Label") + reminderDetailLabel.stringValue = "Set reminders in the timezone of the location of your choice." - calendarHeaderLabel.stringValue = NSLocalizedString("Calendar Access Title", - comment: "Title for Calendar access label") + calendarHeaderLabel.stringValue = NSLocalizedString("Calendar Access Title",comment: "Title for Calendar access label") calendarDetailLabel.stringValue = "Calendar Detail".localized() locationHeaderLabel.stringValue = "Location Access" @@ -160,6 +157,7 @@ class OnboardingPermissionsViewController: NSViewController { @IBAction func locationAction(_: NSButton) { let locationController = LocationController.shared() if locationController.locationAccessNotDetermined() { + locationController.delegate = self locationActivityIndicator.startAnimation(nil) locationController.determineAndRequestLocationAuthorization() } else if locationController.locationAccessDenied() { @@ -167,6 +165,24 @@ class OnboardingPermissionsViewController: NSViewController { } else if locationController.locationAccessGranted() { locationGrantButton.title = "Granted".localized() } - + } + + private func setupLocationButton() { + let locationController = LocationController.shared() + if locationController.locationAccessNotDetermined() { + locationGrantButton.title = "Grant".localized() + } else if locationController.locationAccessDenied() { + locationGrantButton.title = "Denied".localized() + } else if locationController.locationAccessGranted() { + locationGrantButton.title = "Granted".localized() + } + } +} + +extension OnboardingPermissionsViewController: LocationControllerDelegate { + + func didChangeAuthorizationStatus() { + locationActivityIndicator.stopAnimation(nil) + setupLocationButton() } } From 2979c670b0cbff7a701f61148f51c99babc82a22 Mon Sep 17 00:00:00 2001 From: Abhishek Banthia <8280282+n0shake@users.noreply.github.com> Date: Sun, 21 May 2023 03:24:05 +0530 Subject: [PATCH 36/39] Revert "Add location entitlement + info usage description." This reverts commit fa17ef6675709920e75f113f81aeb8269ef581b7. --- Clocker/Clocker/Clocker-Info.plist | 2 -- Clocker/Clocker/Clocker.entitlements | 2 -- 2 files changed, 4 deletions(-) diff --git a/Clocker/Clocker/Clocker-Info.plist b/Clocker/Clocker/Clocker-Info.plist index 70b610e..1de5a47 100755 --- a/Clocker/Clocker/Clocker-Info.plist +++ b/Clocker/Clocker/Clocker-Info.plist @@ -49,7 +49,5 @@ YES ITSAppUsesNonExemptEncryption - NSLocationWhenInUseUsageDescription - Clocker uses your location to auto-update the timezone of your local timezone. diff --git a/Clocker/Clocker/Clocker.entitlements b/Clocker/Clocker/Clocker.entitlements index a18c3ea..9f43c40 100644 --- a/Clocker/Clocker/Clocker.entitlements +++ b/Clocker/Clocker/Clocker.entitlements @@ -10,8 +10,6 @@ com.apple.security.personal-information.calendars - com.apple.security.personal-information.location - com.apple.security.temporary-exception.apple-events com.apple.reminders From 599cc0f85f903c1a822dc57927136b7f59167110 Mon Sep 17 00:00:00 2001 From: Abhishek Banthia <8280282+n0shake@users.noreply.github.com> Date: Sun, 21 May 2023 03:24:32 +0530 Subject: [PATCH 37/39] Update AppDefaults.swift --- Clocker/Overall App/AppDefaults.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Clocker/Overall App/AppDefaults.swift b/Clocker/Overall App/AppDefaults.swift index d0b80f7..99cbdd2 100644 --- a/Clocker/Overall App/AppDefaults.swift +++ b/Clocker/Overall App/AppDefaults.swift @@ -45,7 +45,7 @@ class AppDefaults { extension UserDefaults { // Use this with caution. Exposing this for debugging purposes only. - func wipe(for bundleID: String) { + func wipe(for bundleID: String = "com.abhishek.Clocker") { removePersistentDomain(forName: bundleID) } } From 32c517b60c32b19d1fbe59c9f06e40c31c2495da Mon Sep 17 00:00:00 2001 From: Abhishek Banthia <8280282+n0shake@users.noreply.github.com> Date: Sun, 21 May 2023 03:25:36 +0530 Subject: [PATCH 38/39] Update LocationController.swift --- Clocker/Clocker/LocationController.swift | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Clocker/Clocker/LocationController.swift b/Clocker/Clocker/LocationController.swift index 3b43b9c..60eb8a2 100644 --- a/Clocker/Clocker/LocationController.swift +++ b/Clocker/Clocker/LocationController.swift @@ -11,9 +11,7 @@ protocol LocationControllerDelegate: NSObject { class LocationController: NSObject { private let store: DataStore - private static var sharedController = LocationController(withStore: DataStore.shared()) - weak var delegate: LocationControllerDelegate? - + init(withStore dataStore: DataStore) { store = dataStore super.init() @@ -24,10 +22,6 @@ class LocationController: NSObject { locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers return locationManager }() - - class func shared() -> LocationController { - return sharedController - } func authorizationStatus() -> CLAuthorizationStatus { return CLLocationManager.authorizationStatus() @@ -61,9 +55,7 @@ class LocationController: NSObject { case .authorizedAlways: locationManager.startUpdatingLocation() case .notDetermined: - if #available(macOS 10.15, *) { - locationManager.requestWhenInUseAuthorization() - } + locationManager.startUpdatingLocation() case .denied, .restricted: locationManager.startUpdatingLocation() default: From 00e0d279676357ffbc44b6c1ac31140bc997c846 Mon Sep 17 00:00:00 2001 From: Abhishek Banthia <8280282+n0shake@users.noreply.github.com> Date: Sun, 21 May 2023 03:31:35 +0530 Subject: [PATCH 39/39] Revert location changes. --- Clocker/Clocker/LocationController.swift | 1 - Clocker/Onboarding/Onboarding.storyboard | 81 +++---------------- .../OnboardingPermissionsViewController.swift | 59 +++----------- 3 files changed, 24 insertions(+), 117 deletions(-) diff --git a/Clocker/Clocker/LocationController.swift b/Clocker/Clocker/LocationController.swift index 60eb8a2..9a182d4 100644 --- a/Clocker/Clocker/LocationController.swift +++ b/Clocker/Clocker/LocationController.swift @@ -118,7 +118,6 @@ extension LocationController: CLLocationManagerDelegate { } else if status == .notDetermined || status == .authorized || status == .authorizedAlways { locationManager.startUpdatingLocation() } - delegate?.didChangeAuthorizationStatus() } func locationManager(_: CLLocationManager, didFailWithError error: Error) { diff --git a/Clocker/Onboarding/Onboarding.storyboard b/Clocker/Onboarding/Onboarding.storyboard index b854fdc..fa0972e 100644 --- a/Clocker/Onboarding/Onboarding.storyboard +++ b/Clocker/Onboarding/Onboarding.storyboard @@ -168,10 +168,10 @@ DQ - + - + @@ -179,7 +179,7 @@ DQ - + @@ -197,7 +197,7 @@ DQ - + @@ -208,17 +208,17 @@ DQ - + - + - + @@ -226,7 +226,7 @@ DQ - + @@ -234,7 +234,7 @@ DQ - + @@ -242,7 +242,7 @@ DQ - + @@ -266,7 +266,7 @@ DQ - + @@ -297,65 +297,15 @@ DQ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -371,11 +321,6 @@ DQ - - - - - diff --git a/Clocker/Onboarding/OnboardingPermissionsViewController.swift b/Clocker/Onboarding/OnboardingPermissionsViewController.swift index f7e8588..70f6048 100644 --- a/Clocker/Onboarding/OnboardingPermissionsViewController.swift +++ b/Clocker/Onboarding/OnboardingPermissionsViewController.swift @@ -6,7 +6,6 @@ import CoreLoggerKit class OnboardingPermissionsViewController: NSViewController { @IBOutlet var reminderGrantButton: NSButton! @IBOutlet var calendarGrantButton: NSButton! - @IBOutlet var locationGrantButton: NSButton! @IBOutlet var reminderView: NSView! @IBOutlet var calendarView: NSView! @@ -32,7 +31,7 @@ class OnboardingPermissionsViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - [calendarView, reminderView, locationView].forEach { $0?.applyShadow() } + [calendarView, reminderView].forEach { $0?.applyShadow() } setup() } @@ -46,29 +45,25 @@ class OnboardingPermissionsViewController: NSViewController { onboardingTypeLabel.stringValue = "Your data doesn't leave your device 🔐" reminderHeaderLabel.stringValue = NSLocalizedString("Reminders Access Title",comment: "Title for Reminders Access Label") - reminderDetailLabel.stringValue = "Set reminders in the timezone of the location of your choice." + reminderDetailLabel.stringValue = "Set reminders in the timezone of the location of your choice. Your reminders are stored in the default Reminders app." calendarHeaderLabel.stringValue = NSLocalizedString("Calendar Access Title",comment: "Title for Calendar access label") calendarDetailLabel.stringValue = "Calendar Detail".localized() - - locationHeaderLabel.stringValue = "Location Access" - locationDetailLabel.stringValue = "Accurately track your local time; especially useful if you travel." [calendarHeaderLabel, calendarDetailLabel, privacyLabel, reminderDetailLabel, reminderHeaderLabel, onboardingTypeLabel, appLabel].forEach { $0?.textColor = Themer.shared().mainTextColor() } } private func setupButtons() { - let locationController = LocationController.shared() - if locationController.locationAccessGranted() { - locationGrantButton.title = "Granted" - } else if locationController.locationAccessDenied() { - locationGrantButton.title = "Denied" - } else if locationController.locationAccessNotDetermined() { - locationGrantButton.title = "Grant" - } else { - locationGrantButton.title = "Unexpected" - } +// if LocationController.sharedInstance.locationAccessGranted() { +// locationButton.title = "Granted" +// } else if LocationController.sharedInstance.locationAccessDenied() { +// locationButton.title = "Denied" +// } else if LocationController.sharedInstance.locationAccessNotDetermined() { +// locationButton.title = "Grant" +// } else { +// locationButton.title = "Unexpected" +// } if EventCenter.sharedCenter().calendarAccessGranted() { calendarGrantButton.title = "Granted".localized() @@ -153,36 +148,4 @@ class OnboardingPermissionsViewController: NSViewController { reminderGrantButton.title = "Denied".localized() } } - - @IBAction func locationAction(_: NSButton) { - let locationController = LocationController.shared() - if locationController.locationAccessNotDetermined() { - locationController.delegate = self - locationActivityIndicator.startAnimation(nil) - locationController.determineAndRequestLocationAuthorization() - } else if locationController.locationAccessDenied() { - locationGrantButton.title = "Denied".localized() - } else if locationController.locationAccessGranted() { - locationGrantButton.title = "Granted".localized() - } - } - - private func setupLocationButton() { - let locationController = LocationController.shared() - if locationController.locationAccessNotDetermined() { - locationGrantButton.title = "Grant".localized() - } else if locationController.locationAccessDenied() { - locationGrantButton.title = "Denied".localized() - } else if locationController.locationAccessGranted() { - locationGrantButton.title = "Granted".localized() - } - } -} - -extension OnboardingPermissionsViewController: LocationControllerDelegate { - - func didChangeAuthorizationStatus() { - locationActivityIndicator.stopAnimation(nil) - setupLocationButton() - } }