Browse Source

Things are working, let's commit before we find any other bugs.

pull/101/head
Abhishek 4 years ago
parent
commit
f78e61669e
  1. 16
      Clocker/Clocker/en.lproj/Panel.xib
  2. 9
      Clocker/ClockerUITests/PanelTests.swift
  3. 4
      Clocker/Overall App/Themer.swift
  4. 4
      Clocker/Panel/PanelController.swift
  5. 84
      Clocker/Panel/ParentPanelController+ModernSlider.swift
  6. 25
      Clocker/Panel/ParentPanelController.swift
  7. 5
      Clocker/Panel/UI/HourMarkerViewItem.swift
  8. 3
      Clocker/Preferences/General/SearchDataSource.swift

16
Clocker/Clocker/en.lproj/Panel.xib

@ -49,10 +49,10 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<stackView focusRingType="none" distribution="fill" orientation="vertical" alignment="leading" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OZA-6o-SbE"> <stackView focusRingType="none" distribution="fill" orientation="vertical" alignment="leading" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OZA-6o-SbE">
<rect key="frame" x="0.0" y="0.0" width="350" height="315"/> <rect key="frame" x="0.0" y="0.0" width="350" height="320"/>
<subviews> <subviews>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="96" horizontalPageScroll="1" verticalLineScroll="96" verticalPageScroll="1" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="light" translatesAutoresizingMaskIntoConstraints="NO" id="4Gd-Nv-fXr"> <scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="96" horizontalPageScroll="1" verticalLineScroll="96" verticalPageScroll="1" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="light" translatesAutoresizingMaskIntoConstraints="NO" id="4Gd-Nv-fXr">
<rect key="frame" x="-20" y="50" width="370" height="265"/> <rect key="frame" x="-20" y="55" width="370" height="265"/>
<clipView key="contentView" focusRingType="none" drawsBackground="NO" copiesOnScroll="NO" id="4MZ-Di-yNR"> <clipView key="contentView" focusRingType="none" drawsBackground="NO" copiesOnScroll="NO" id="4MZ-Di-yNR">
<rect key="frame" x="0.0" y="0.0" width="370" height="265"/> <rect key="frame" x="0.0" y="0.0" width="370" height="265"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -262,7 +262,7 @@
</scroller> </scroller>
</scrollView> </scrollView>
<customView identifier="Review Cell" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="TDn-Kk-KkV"> <customView identifier="Review Cell" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="TDn-Kk-KkV">
<rect key="frame" x="0.0" y="0.0" width="350" height="50"/> <rect key="frame" x="0.0" y="220" width="350" height="50"/>
<subviews> <subviews>
<stackView focusRingType="none" distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uys-ww-duA"> <stackView focusRingType="none" distribution="fill" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uys-ww-duA">
<rect key="frame" x="25" y="25" width="300" height="20"/> <rect key="frame" x="25" y="25" width="300" height="20"/>
@ -336,7 +336,7 @@
<accessibility description="ReviewCell" identifier="ReviewCell"/> <accessibility description="ReviewCell" identifier="ReviewCell"/>
</customView> </customView>
<customView wantsLayer="YES" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="Akn-cR-W4G" customClass="ReviewView" customModule="Clocker" customModuleProvider="target"> <customView wantsLayer="YES" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="Akn-cR-W4G" customClass="ReviewView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="0.0" y="-75" width="350" height="75"/> <rect key="frame" x="0.0" y="145" width="350" height="75"/>
<subviews> <subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Etf-aa-udM" customClass="ClockerTextBackgroundView" customModule="Clocker" customModuleProvider="target"> <customView translatesAutoresizingMaskIntoConstraints="NO" id="Etf-aa-udM" customClass="ClockerTextBackgroundView" customModule="Clocker" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="330" height="55"/> <rect key="frame" x="10" y="10" width="330" height="55"/>
@ -413,7 +413,7 @@
<accessibility identifier="UpcomingEventView"/> <accessibility identifier="UpcomingEventView"/>
</customView> </customView>
<customView wantsLayer="YES" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="C7R-Dq-MFr" userLabel="Slider View"> <customView wantsLayer="YES" focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="C7R-Dq-MFr" userLabel="Slider View">
<rect key="frame" x="0.0" y="110" width="350" height="30"/> <rect key="frame" x="0.0" y="115" width="350" height="30"/>
<subviews> <subviews>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Vf2-uI-yf3"> <slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Vf2-uI-yf3">
<rect key="frame" x="7" y="2" width="201" height="23"/> <rect key="frame" x="7" y="2" width="201" height="23"/>
@ -462,7 +462,7 @@
</constraints> </constraints>
</customView> </customView>
<customView wantsLayer="YES" focusRingType="none" id="8W7-rS-Uob" userLabel="Modern Slider"> <customView wantsLayer="YES" focusRingType="none" id="8W7-rS-Uob" userLabel="Modern Slider">
<rect key="frame" x="0.0" y="40" width="350" height="70"/> <rect key="frame" x="0.0" y="40" width="350" height="75"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews> <subviews>
<scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="htc-pO-AqH"> <scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="htc-pO-AqH">
@ -507,9 +507,9 @@
</textField> </textField>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5HT-Ps-YH3"/> <constraint firstAttribute="height" constant="75" id="5HT-Ps-YH3"/>
<constraint firstAttribute="bottom" secondItem="pi8-wk-eXa" secondAttribute="bottom" constant="3" id="6E6-8S-PZv"/> <constraint firstAttribute="bottom" secondItem="pi8-wk-eXa" secondAttribute="bottom" constant="3" id="6E6-8S-PZv"/>
<constraint firstItem="htc-pO-AqH" firstAttribute="top" secondItem="8W7-rS-Uob" secondAttribute="top" id="Ag8-2G-tVA"/> <constraint firstItem="htc-pO-AqH" firstAttribute="top" secondItem="8W7-rS-Uob" secondAttribute="top" constant="5" id="Ag8-2G-tVA"/>
<constraint firstItem="htc-pO-AqH" firstAttribute="leading" secondItem="8W7-rS-Uob" secondAttribute="leading" constant="5" id="QmJ-Dd-WLb"/> <constraint firstItem="htc-pO-AqH" firstAttribute="leading" secondItem="8W7-rS-Uob" secondAttribute="leading" constant="5" id="QmJ-Dd-WLb"/>
<constraint firstItem="pi8-wk-eXa" firstAttribute="top" secondItem="htc-pO-AqH" secondAttribute="bottom" constant="5" id="UIT-XA-SEL"/> <constraint firstItem="pi8-wk-eXa" firstAttribute="top" secondItem="htc-pO-AqH" secondAttribute="bottom" constant="5" id="UIT-XA-SEL"/>
<constraint firstAttribute="bottom" secondItem="htc-pO-AqH" secondAttribute="bottom" constant="30" id="YCJ-zB-dvc"/> <constraint firstAttribute="bottom" secondItem="htc-pO-AqH" secondAttribute="bottom" constant="30" id="YCJ-zB-dvc"/>

9
Clocker/ClockerUITests/PanelTests.swift

@ -115,4 +115,13 @@ class PanelTests: XCTestCase {
XCTAssert(app.popovers.count > 0) XCTAssert(app.popovers.count > 0)
} }
// Ensure that once main panel is closed, the time in the menubar doesn't stop and stays up-to-date
func testTimeIsUpToDate() {
// Ensure that we have seconds selected for the timezone format
// Open Panel; before closing panel note the time
// Close Panel;
// Start timer;
// Check time increments or is not equal for all those five seconds?
}
} }

4
Clocker/Overall App/Themer.swift

@ -187,8 +187,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 {

4
Clocker/Panel/PanelController.swift

@ -95,8 +95,8 @@ class PanelController: ParentPanelController {
// Reset future slider value to zero // Reset future slider value to zero
futureSlider.integerValue = 0 futureSlider.integerValue = 0
sliderDatePicker.dateValue = Date() sliderDatePicker.dateValue = Date()
modernSliderLabel.stringValue = modernSliderDataSource[modernSliderDataSource.count / 2] closestQuarterTimeRepresentation = setModernLabel()
let indexPaths: Set<IndexPath> = Set([IndexPath(item: modernSliderDataSource.count / 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)
setTimezoneDatasourceSlider(sliderValue: 0) setTimezoneDatasourceSlider(sliderValue: 0)

84
Clocker/Panel/ParentPanelController+ModernSlider.swift

@ -5,13 +5,12 @@ import Foundation
extension ParentPanelController: NSCollectionViewDataSource, NSCollectionViewDelegate { extension ParentPanelController: NSCollectionViewDataSource, NSCollectionViewDelegate {
func collectionView(_: NSCollectionView, numberOfItemsInSection _: Int) -> Int { func collectionView(_: NSCollectionView, numberOfItemsInSection _: Int) -> Int {
return modernSliderDataSource.count return (96 * PanelConstants.modernSliderDaySupport * 2) + 1
} }
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: HourMarkerViewItem.reuseIdentifier, for: indexPath) as! HourMarkerViewItem let item = collectionView.makeItem(withIdentifier: HourMarkerViewItem.reuseIdentifier, for: indexPath) as! HourMarkerViewItem
let dataSoureValue = modernSliderDataSource[indexPath.item] item.setup(with: indexPath.item)
item.setup(with: indexPath.item, value: dataSoureValue)
return item return item
} }
} }
@ -22,10 +21,56 @@ extension ParentPanelController {
let changedOrigin = contentView.documentVisibleRect.origin let changedOrigin = contentView.documentVisibleRect.origin
let newPoint = NSPoint(x: changedOrigin.x + contentView.frame.width / 2, y: changedOrigin.y) let newPoint = NSPoint(x: changedOrigin.x + contentView.frame.width / 2, y: changedOrigin.y)
let indexPath = modernSlider.indexPathForItem(at: newPoint) let indexPath = modernSlider.indexPathForItem(at: newPoint)
if let correctIndexPath = indexPath?.item { if let correctIndexPath = indexPath?.item, currentCenterIndexPath != correctIndexPath {
modernSliderLabel.stringValue = modernSliderDataSource[correctIndexPath] currentCenterIndexPath = correctIndexPath
// setTimezoneDatasourceSlider(sliderValue: item.indexTag * 15) let minutesToAdd = setDefaultDateLabel(correctIndexPath)
// mainTableView.reloadData() setTimezoneDatasourceSlider(sliderValue: minutesToAdd)
mainTableView.reloadData()
}
}
@objc func scrollViewWillStartLiveScroll(_: NSNotification) {
modernSliderIsScrolling = true
}
@objc func scrollViewDidEndLiveScroll(_: NSNotification) {
modernSliderIsScrolling = false
}
@discardableResult
public func setModernLabel(_ shouldUpdate: Bool = false) -> Date {
let defaultParameters = minuteFromCalendar()
let hourQuarterDate = Calendar.current.nextDate(after: defaultParameters.0,
matching: DateComponents(minute: defaultParameters.1),
matchingPolicy: .strict,
repeatedTimePolicy: .first,
direction: .forward)!
if shouldUpdate {
modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(hourQuarterDate)
} else {
modernSliderLabel.stringValue = CLEmptyString
}
return hourQuarterDate
}
public func setDefaultDateLabel(_ index: Int) -> Int {
let totalCount = (96 * PanelConstants.modernSliderDaySupport * 2) + 1
let centerPoint = Int(ceil(Double(totalCount / 2)))
if index > (centerPoint + 1) {
let remainder = (index % (centerPoint + 1))
let nextDate = Calendar.current.date(byAdding: .minute, value: remainder * 15, to: closestQuarterTimeRepresentation ?? Date())!
modernSliderLabel.stringValue = timezoneFormattedStringRepresentation(nextDate)
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)
return previousDate.minutes(from: Date())
} else {
setModernLabel(true)
return 0
} }
} }
@ -45,31 +90,6 @@ extension ParentPanelController {
return (currentDate, minute) return (currentDate, minute)
} }
public func forward15Minutes() -> [String] {
let defaultParameters = minuteFromCalendar()
var hourQuarterDate = Calendar.current.nextDate(after: defaultParameters.0, matching: DateComponents(minute: defaultParameters.1), matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .forward)!
var hourQuarters = [String]()
hourQuarters.append(timezoneFormattedStringRepresentation(hourQuarterDate))
for _ in 1 ... 288 {
hourQuarterDate = Calendar.current.date(byAdding: .minute, value: 15, to: hourQuarterDate)!
hourQuarters.append(timezoneFormattedStringRepresentation(hourQuarterDate))
}
return hourQuarters
}
public func backward15Minutes() -> [String] {
let defaultParameters = minuteFromCalendar()
var hourQuarterDate = Calendar.current.nextDate(after: defaultParameters.0, matching: DateComponents(minute: defaultParameters.1), matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .backward)!
var hourQuarters = [String]()
for _ in 1 ... 288 {
hourQuarterDate = Calendar.current.date(byAdding: .minute, value: -15, to: hourQuarterDate)!
hourQuarters.append(timezoneFormattedStringRepresentation(hourQuarterDate))
}
return hourQuarters
}
private func timezoneFormattedStringRepresentation(_ date: Date) -> String { private func timezoneFormattedStringRepresentation(_ date: Date) -> String {
let dateFormatter = DateFormatterManager.dateFormatterWithFormat(with: .none, let dateFormatter = DateFormatterManager.dateFormatterWithFormat(with: .none,
format: "MMM d HH:mm", format: "MMM d HH:mm",

25
Clocker/Panel/ParentPanelController.swift

@ -11,6 +11,7 @@ struct PanelConstants {
static let noThanksTitle = "No, thanks" static let noThanksTitle = "No, thanks"
static let yesWithQuestionMark = "Yes?" static let yesWithQuestionMark = "Yes?"
static let yesWithExclamation = "Yes!" static let yesWithExclamation = "Yes!"
static let modernSliderDaySupport = 7
} }
class ParentPanelController: NSWindowController { class ParentPanelController: NSWindowController {
@ -86,7 +87,9 @@ class ParentPanelController: NSWindowController {
@IBOutlet var roundedDateView: NSView! @IBOutlet var roundedDateView: NSView!
// Modern Slider // Modern Slider
public var modernSliderDataSource: [String] = [] public var currentCenterIndexPath: Int = -1
public var closestQuarterTimeRepresentation: Date?
public var modernSliderIsScrolling: Bool = false
@IBOutlet var modernSlider: NSCollectionView! @IBOutlet var modernSlider: NSCollectionView!
@IBOutlet var modernSliderLabel: NSTextField! @IBOutlet var modernSliderLabel: NSTextField!
@IBOutlet var modernContainerView: NSView! @IBOutlet var modernContainerView: NSView!
@ -198,20 +201,23 @@ class ParentPanelController: NSWindowController {
} }
if modernSlider != nil { if modernSlider != nil {
var backwards = backward15Minutes()
backwards.reverse()
let forwards = forward15Minutes()
modernSliderDataSource = backwards + forwards
modernSlider.enclosingScrollView?.scrollerInsets = NSEdgeInsets(top: 0, left: 0, bottom: 100, right: 0) modernSlider.enclosingScrollView?.scrollerInsets = NSEdgeInsets(top: 0, left: 0, bottom: 100, right: 0)
modernSlider.delegate = self modernSlider.delegate = self
modernSlider.postsBoundsChangedNotifications = true modernSlider.postsBoundsChangedNotifications = true
NotificationCenter.default.addObserver(self,
selector: #selector(scrollViewWillStartLiveScroll(_:)),
name: NSScrollView.willStartLiveScrollNotification,
object: modernSlider.enclosingScrollView)
NotificationCenter.default.addObserver(self,
selector: #selector(scrollViewDidEndLiveScroll(_:)),
name: NSScrollView.didEndLiveScrollNotification,
object: modernSlider.enclosingScrollView)
NotificationCenter.default.addObserver(self, NotificationCenter.default.addObserver(self,
selector: #selector(collectionViewDidScroll(_:)), selector: #selector(collectionViewDidScroll(_:)),
name: NSView.boundsDidChangeNotification, name: NSView.boundsDidChangeNotification,
object: modernSlider.superview) object: modernSlider.superview)
modernSliderLabel.stringValue = modernSliderDataSource[modernSliderDataSource.count / 2] closestQuarterTimeRepresentation = setModernLabel()
let indexPaths: Set<IndexPath> = Set([IndexPath(item: modernSliderDataSource.count / 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)
} }
@ -595,7 +601,7 @@ class ParentPanelController: NSWindowController {
if let futureSliderCell = futureSlider.cell as? CustomSliderCell, futureSliderCell.tracking == true { if let futureSliderCell = futureSlider.cell as? CustomSliderCell, futureSliderCell.tracking == true {
return return
} }
if modernSlider.isHidden == false { if modernSlider.isHidden == false, modernSliderIsScrolling {
return return
} }
let dataOperation = TimezoneDataOperations(with: model) let dataOperation = TimezoneDataOperations(with: model)
@ -615,6 +621,7 @@ class ParentPanelController: NSWindowController {
} }
cellView.layout(with: model) cellView.layout(with: model)
updateDatePicker() updateDatePicker()
setModernLabel()
} }
} }
} }

5
Clocker/Panel/UI/HourMarkerViewItem.swift

@ -4,11 +4,8 @@ import Cocoa
class HourMarkerViewItem: NSCollectionViewItem { class HourMarkerViewItem: NSCollectionViewItem {
static let reuseIdentifier = NSUserInterfaceItemIdentifier("HourMarkerViewItem") static let reuseIdentifier = NSUserInterfaceItemIdentifier("HourMarkerViewItem")
public var timeRepresentation: String = "-1"
func setup(with index: Int, value: String) {
timeRepresentation = value
func setup(with index: Int) {
for constraint in view.constraints where constraint.identifier == "constrainFromTop" { for constraint in view.constraints where constraint.identifier == "constrainFromTop" {
if index % 4 == 0 { if index % 4 == 0 {
constraint.constant = 0 constraint.constant = 0

3
Clocker/Preferences/General/SearchDataSource.swift

@ -66,6 +66,9 @@ class SearchDataSource: NSObject {
let datasource = searchField.stringValue.isEmpty ? timezoneArray : timezoneFilteredArray let datasource = searchField.stringValue.isEmpty ? timezoneArray : timezoneFilteredArray
return datasource[row % datasource.count] return datasource[row % datasource.count]
case .city: case .city:
if filteredArray.count == 0 {
return nil
}
let timezoneData = filteredArray[row % filteredArray.count] let timezoneData = filteredArray[row % filteredArray.count]
return timezoneData return timezoneData
} }

Loading…
Cancel
Save