diff --git a/Clocker/Clocker/en.lproj/Panel.xib b/Clocker/Clocker/en.lproj/Panel.xib index 1f8afdd..8265f84 100755 --- a/Clocker/Clocker/en.lproj/Panel.xib +++ b/Clocker/Clocker/en.lproj/Panel.xib @@ -22,6 +22,7 @@ + @@ -44,14 +45,14 @@ - + - + - + @@ -261,7 +262,7 @@ - + @@ -310,7 +311,7 @@ - + @@ -364,6 +365,20 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + - - - - - + + + + + @@ -526,7 +556,7 @@ + - + - - + - + @@ -650,6 +680,7 @@ + diff --git a/Clocker/Overall App/Themer.swift b/Clocker/Overall App/Themer.swift index 42f7027..688cd54 100644 --- a/Clocker/Overall App/Themer.swift +++ b/Clocker/Overall App/Themer.swift @@ -210,8 +210,8 @@ extension Themer { return themeIndex == .light - ? NSImage(named: NSImage.Name("Settings"))! - : NSImage(named: NSImage.Name("Settings-White"))! + ? NSImage(named: NSImage.Name("Settings"))! + : NSImage(named: NSImage.Name("Settings-White"))! } func pinImage() -> NSImage { @@ -515,6 +515,10 @@ extension Themer { return symbolImage(for: "goforward.15") } + func resetModernSliderImage() -> NSImage? { + return symbolImage(for: "xmark.circle.fill") + } + private func symbolImage(for name: String) -> NSImage? { assert(name.isEmpty == false) diff --git a/Clocker/Panel/PanelController.swift b/Clocker/Panel/PanelController.swift index 7a66f2a..5464c4d 100644 --- a/Clocker/Panel/PanelController.swift +++ b/Clocker/Panel/PanelController.swift @@ -99,6 +99,7 @@ class PanelController: ParentPanelController { sliderDatePicker.dateValue = Date() closestQuarterTimeRepresentation = findClosestQuarterTimeApproximation() modernSliderLabel.stringValue = "Time Scroller" + resetModernSliderButton.isHidden = true if modernSlider != nil { let indexPaths: Set = Set([IndexPath(item: modernSlider.numberOfItems(inSection: 0) / 2, section: 0)]) diff --git a/Clocker/Panel/ParentPanelController+ModernSlider.swift b/Clocker/Panel/ParentPanelController+ModernSlider.swift index bab5d2e..06c6d50 100644 --- a/Clocker/Panel/ParentPanelController+ModernSlider.swift +++ b/Clocker/Panel/ParentPanelController+ModernSlider.swift @@ -18,6 +18,8 @@ extension ParentPanelController: NSCollectionViewDataSource { extension ParentPanelController { func setupModernSliderIfNeccessary() { if modernSlider != nil { + resetModernSliderButton.image = Themer.shared().resetModernSliderImage() + goBackwardsButton.image = Themer.shared().goBackwardsImage() goForwardButton.image = Themer.shared().goForwardsImage() @@ -56,6 +58,27 @@ extension ParentPanelController { navigateModernSliderToSpecificIndex(-1) } + private func animateButton(_ hidden: Bool) { + NSAnimationContext.runAnimationGroup({ context in + context.duration = 0.5 + context.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) + resetModernSliderButton.animator().alphaValue = hidden ? 0.0 : 1.0 + }, completionHandler: { [weak self] in + guard let strongSelf = self else { return } + strongSelf.resetModernSliderButton.animator().isHidden = hidden + }) + } + + @IBAction func resetModernSlider(_: NSButton) { + closestQuarterTimeRepresentation = findClosestQuarterTimeApproximation() + modernSliderLabel.stringValue = "Time Scroller" + animateButton(true) + if modernSlider != nil { + let indexPaths: Set = Set([IndexPath(item: modernSlider.numberOfItems(inSection: 0) / 2, section: 0)]) + modernSlider.scrollToItems(at: indexPaths, scrollPosition: .centeredHorizontally) + } + } + private func navigateModernSliderToSpecificIndex(_ index: Int) { guard let contentView = modernSlider.superview as? NSClipView else { return @@ -101,14 +124,24 @@ extension ParentPanelController { let remainder = (index % (centerPoint + 1)) let nextDate = Calendar.current.date(byAdding: .minute, value: remainder * 15, to: closestQuarterTimeRepresentation ?? Date())! modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(nextDate) + if resetModernSliderButton.isHidden { + animateButton(false) + } + return nextDate.minutes(from: Date()) + 1 } else if index < centerPoint { let remainder = centerPoint - index + 1 let previousDate = Calendar.current.date(byAdding: .minute, value: -1 * remainder * 15, to: closestQuarterTimeRepresentation ?? Date())! modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(previousDate) + if resetModernSliderButton.isHidden { + animateButton(false) + } return previousDate.minutes(from: Date()) } else { modernSliderLabel.stringValue = "Time Scroller" + if !resetModernSliderButton.isHidden { + animateButton(true) + } return 0 } } diff --git a/Clocker/Panel/ParentPanelController.swift b/Clocker/Panel/ParentPanelController.swift index b01cfc7..c17a01d 100644 --- a/Clocker/Panel/ParentPanelController.swift +++ b/Clocker/Panel/ParentPanelController.swift @@ -85,6 +85,7 @@ class ParentPanelController: NSWindowController { @IBOutlet var modernContainerView: ModernSliderContainerView! @IBOutlet var goBackwardsButton: NSButton! @IBOutlet var goForwardButton: NSButton! + @IBOutlet var resetModernSliderButton: NSButton! // Upcoming Events @IBOutlet var upcomingEventCollectionView: NSCollectionView! @@ -543,7 +544,7 @@ class ParentPanelController: NSWindowController { @IBAction func openPreferences(_: NSButton) { updatePopoverDisplayState() // Popover's class has access to all timezones. Need to close the popover, so that we don't have two copies of selections - openPreferences() + openPreferencesWindow() } func deleteTimezone(at row: Int) { @@ -682,7 +683,7 @@ class ParentPanelController: NSWindowController { mainTableView.reloadData() } - private func openPreferences() { + @objc private func openPreferencesWindow() { oneWindow?.showWindow(nil) NSApp.activate(ignoringOtherApps: true) } @@ -870,10 +871,6 @@ class ParentPanelController: NSWindowController { } else { updateReviewView() ReviewController.prompt() - - if let countryCode = Locale.autoupdatingCurrent.regionCode { - Logger.log(object: ["CurrentCountry": countryCode], for: "Remind Later for Feedback") - } } } @@ -1000,6 +997,8 @@ class ParentPanelController: NSWindowController { action: #selector(reportIssue), keyEquivalent: "") let localizeClocker = NSMenuItem(title: "Localize Clocker...", action: #selector(openCrowdin), keyEquivalent: "") + let openPreferences = NSMenuItem(title: "Preferences", + action: #selector(openPreferencesWindow), keyEquivalent: "") let appDisplayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") ?? "Clocker" let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "N/A" @@ -1008,6 +1007,7 @@ class ParentPanelController: NSWindowController { let versionInfo = "\(appDisplayName) \(shortVersion) (\(longVersion))" let clockerVersionInfo = NSMenuItem(title: versionInfo, action: nil, keyEquivalent: "") clockerVersionInfo.isEnabled = false + menuItem.addItem(openPreferences) menuItem.addItem(rateClocker) menuItem.addItem(sendFeedback) menuItem.addItem(localizeClocker) diff --git a/Clocker/Panel/UI/FloatingWindow.xib b/Clocker/Panel/UI/FloatingWindow.xib index 3f15c9a..a79a1e6 100644 --- a/Clocker/Panel/UI/FloatingWindow.xib +++ b/Clocker/Panel/UI/FloatingWindow.xib @@ -44,22 +44,22 @@ - + - + - + - + - + @@ -292,7 +292,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -404,7 +404,7 @@ - + + + - - + - diff --git a/Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift b/Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift index 0f01146..4a63ea0 100644 --- a/Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift +++ b/Clocker/Panel/Upcoming Events/UpcomingEventViewItem.swift @@ -33,7 +33,7 @@ class UpcomingEventViewItem: NSCollectionViewItem { calendarColorView.layer?.backgroundColor = color.cgColor setCalendarButtonTitle(buttonTitle: subtitle) panelDelegate = delegate - + if isCancelled { let strikethroughString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.strikethroughStyle: NSUnderlineStyle.single.rawValue, NSAttributedString.Key.strikethroughColor: NSColor.gray])