Repository: kaunteya/ProgressKit
Branch: master
Commit: f19f111ec32a
Files: 28
Total size: 194.9 KB
Directory structure:
gitextract_lvo65_ut/
├── .gitignore
├── .swift-version
├── BaseView.swift
├── Determinate/
│ ├── CircularProgressView.swift
│ ├── DeterminateAnimation.swift
│ └── ProgressBar.swift
├── InDeterminate/
│ ├── Crawler.swift
│ ├── IndeterminateAnimation.swift
│ ├── MaterialProgress.swift
│ ├── Rainbow.swift
│ ├── RotatingArc.swift
│ ├── ShootingStars.swift
│ └── Spinner.swift
├── LICENSE
├── ProgressKit/
│ ├── AppDelegate.swift
│ ├── Base.lproj/
│ │ └── Main.storyboard
│ ├── Determinate.swift
│ ├── DeterminateVC.swift
│ ├── InDeterminate.swift
│ ├── InDeterminateVC.swift
│ └── Info.plist
├── ProgressKit.podspec
├── ProgressKit.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── ProgressKitTests/
│ ├── Info.plist
│ └── ProgressKitTests.swift
├── ProgressUtils.swift
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
================================================
FILE: .swift-version
================================================
3.0
================================================
FILE: BaseView.swift
================================================
//
// BaseView.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 04/10/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import AppKit
@IBDesignable
open class BaseView : NSView {
override public init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.configureLayers()
}
required public init?(coder: NSCoder) {
super.init(coder: coder)
self.configureLayers()
}
/// Configure the Layers
func configureLayers() {
self.wantsLayer = true
notifyViewRedesigned()
}
@IBInspectable open var background: NSColor = NSColor(red: 88.3 / 256, green: 104.4 / 256, blue: 118.5 / 256, alpha: 1.0) {
didSet {
self.notifyViewRedesigned()
}
}
@IBInspectable open var foreground: NSColor = NSColor(red: 66.3 / 256, green: 173.7 / 256, blue: 106.4 / 256, alpha: 1.0) {
didSet {
self.notifyViewRedesigned()
}
}
@IBInspectable open var cornerRadius: CGFloat = 5.0 {
didSet {
self.notifyViewRedesigned()
}
}
/// Call when any IBInspectable variable is changed
func notifyViewRedesigned() {
self.layer?.backgroundColor = background.cgColor
self.layer?.cornerRadius = cornerRadius
}
}
================================================
FILE: Determinate/CircularProgressView.swift
================================================
//
// CircularView.swift
// Animo
//
// Created by Kauntey Suryawanshi on 29/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
@IBDesignable
open class CircularProgressView: DeterminateAnimation {
open var backgroundCircle = CAShapeLayer()
open var progressLayer = CAShapeLayer()
open var percentLabelLayer = CATextLayer()
@IBInspectable open var strokeWidth: CGFloat = -1 {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var showPercent: Bool = true {
didSet {
notifyViewRedesigned()
}
}
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
backgroundCircle.lineWidth = self.strokeWidth / 2
progressLayer.lineWidth = strokeWidth
percentLabelLayer.isHidden = !showPercent
backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor
progressLayer.strokeColor = foreground.cgColor
percentLabelLayer.foregroundColor = foreground.cgColor
}
override func updateProgress() {
CATransaction.begin()
if animated {
CATransaction.setAnimationDuration(0.5)
} else {
CATransaction.setDisableActions(true)
}
let timing = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
CATransaction.setAnimationTimingFunction(timing)
progressLayer.strokeEnd = max(0, min(progress, 1))
percentLabelLayer.string = "\(Int(progress * 100))%"
CATransaction.commit()
}
override func configureLayers() {
super.configureLayers()
let rect = self.bounds
let radius = (rect.width / 2) * 0.75
let strokeScalingFactor = CGFloat(0.05)
// Add background Circle
do {
backgroundCircle.frame = rect
backgroundCircle.lineWidth = strokeWidth == -1 ? (rect.width * strokeScalingFactor / 2) : strokeWidth / 2
backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor
backgroundCircle.fillColor = NSColor.clear.cgColor
let backgroundPath = NSBezierPath()
backgroundPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360)
backgroundCircle.path = backgroundPath.CGPath
self.layer?.addSublayer(backgroundCircle)
}
// Progress Layer
do {
progressLayer.strokeEnd = 0 //REMOVe this
progressLayer.fillColor = NSColor.clear.cgColor
progressLayer.lineCap = .round
progressLayer.lineWidth = strokeWidth == -1 ? (rect.width * strokeScalingFactor) : strokeWidth
progressLayer.frame = rect
progressLayer.strokeColor = foreground.cgColor
let arcPath = NSBezierPath()
let startAngle = CGFloat(90)
arcPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: startAngle, endAngle: (startAngle - 360), clockwise: true)
progressLayer.path = arcPath.CGPath
self.layer?.addSublayer(progressLayer)
}
// Percentage Layer
do {
percentLabelLayer.string = "0%"
percentLabelLayer.foregroundColor = foreground.cgColor
percentLabelLayer.frame = rect
percentLabelLayer.font = "Helvetica Neue Light" as CFTypeRef
percentLabelLayer.alignmentMode = CATextLayerAlignmentMode.center
percentLabelLayer.position.y = rect.midY * 0.25
percentLabelLayer.fontSize = rect.width * 0.2
self.layer?.addSublayer(percentLabelLayer)
}
}
}
================================================
FILE: Determinate/DeterminateAnimation.swift
================================================
//
// DeterminateAnimation.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 09/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
protocol DeterminableAnimation {
func updateProgress()
}
@IBDesignable
open class DeterminateAnimation: BaseView, DeterminableAnimation {
@IBInspectable open var animated: Bool = true
/// Value of progress now. Range 0..1
@IBInspectable open var progress: CGFloat = 0 {
didSet {
updateProgress()
}
}
/// This function will only be called by didSet of progress. Every subclass will have its own implementation
func updateProgress() {
fatalError("Must be overriden in subclass")
}
}
================================================
FILE: Determinate/ProgressBar.swift
================================================
//
// ProgressBar.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 31/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
@IBDesignable
open class ProgressBar: DeterminateAnimation {
open var borderLayer = CAShapeLayer()
open var progressLayer = CAShapeLayer()
@IBInspectable open var borderColor: NSColor = .black {
didSet {
notifyViewRedesigned()
}
}
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
self.layer?.cornerRadius = self.frame.height / 2
borderLayer.borderColor = borderColor.cgColor
progressLayer.backgroundColor = foreground.cgColor
}
override func configureLayers() {
super.configureLayers()
borderLayer.frame = self.bounds
borderLayer.cornerRadius = borderLayer.frame.height / 2
borderLayer.borderWidth = 1.0
self.layer?.addSublayer(borderLayer)
progressLayer.frame = NSInsetRect(borderLayer.bounds, 3, 3)
progressLayer.frame.size.width = (borderLayer.bounds.width - 6)
progressLayer.cornerRadius = progressLayer.frame.height / 2
progressLayer.backgroundColor = foreground.cgColor
borderLayer.addSublayer(progressLayer)
}
override func updateProgress() {
CATransaction.begin()
if animated {
CATransaction.setAnimationDuration(0.5)
} else {
CATransaction.setDisableActions(true)
}
let timing = CAMediaTimingFunction(name: .easeOut)
CATransaction.setAnimationTimingFunction(timing)
progressLayer.frame.size.width = (borderLayer.bounds.width - 6) * progress
CATransaction.commit()
}
}
================================================
FILE: InDeterminate/Crawler.swift
================================================
//
// Crawler.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 11/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
private let defaultForegroundColor = NSColor.white
private let defaultBackgroundColor = NSColor(white: 0.0, alpha: 0.4)
private let duration = 1.2
@IBDesignable
open class Crawler: IndeterminateAnimation {
var starList = [CAShapeLayer]()
var smallCircleSize: Double {
return Double(self.bounds.width) * 0.2
}
var animationGroups = [CAAnimation]()
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
for star in starList {
star.backgroundColor = foreground.cgColor
}
}
override func configureLayers() {
super.configureLayers()
let rect = self.bounds
let insetRect = NSInsetRect(rect, rect.width * 0.15, rect.width * 0.15)
for i in 0 ..< 5 {
let starShape = CAShapeLayer()
starList.append(starShape)
starShape.backgroundColor = foreground.cgColor
let circleWidth = smallCircleSize - Double(i) * 2
starShape.bounds = CGRect(x: 0, y: 0, width: circleWidth, height: circleWidth)
starShape.cornerRadius = CGFloat(circleWidth / 2)
starShape.position = CGPoint(x: rect.midX, y: rect.midY + insetRect.height / 2)
self.layer?.addSublayer(starShape)
let arcPath = NSBezierPath()
arcPath.appendArc(withCenter: insetRect.mid, radius: insetRect.width / 2, startAngle: 90, endAngle: -360 + 90, clockwise: true)
let rotationAnimation = CAKeyframeAnimation(keyPath: "position")
rotationAnimation.path = arcPath.CGPath
rotationAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
rotationAnimation.beginTime = (duration * 0.075) * Double(i)
rotationAnimation.calculationMode = .cubicPaced
let animationGroup = CAAnimationGroup()
animationGroup.animations = [rotationAnimation]
animationGroup.duration = duration
animationGroup.repeatCount = .infinity
animationGroups.append(animationGroup)
}
}
override func startAnimation() {
for (index, star) in starList.enumerated() {
star.add(animationGroups[index], forKey: "")
}
}
override func stopAnimation() {
for star in starList {
star.removeAllAnimations()
}
}
}
================================================
FILE: InDeterminate/IndeterminateAnimation.swift
================================================
//
// InDeterminateAnimation.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 09/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Cocoa
protocol AnimationStatusDelegate {
func startAnimation()
func stopAnimation()
}
open class IndeterminateAnimation: BaseView, AnimationStatusDelegate {
/// View is hidden when *animate* property is false
@IBInspectable open var displayAfterAnimationEnds: Bool = false
/**
Control point for all Indeterminate animation
True invokes `startAnimation()` on subclass of IndeterminateAnimation
False invokes `stopAnimation()` on subclass of IndeterminateAnimation
*/
open var animate: Bool = false {
didSet {
guard animate != oldValue else { return }
if animate {
self.isHidden = false
startAnimation()
} else {
if !displayAfterAnimationEnds {
self.isHidden = true
}
stopAnimation()
}
}
}
/**
Every function that extends Indeterminate animation must define startAnimation().
`animate` property of Indeterminate animation will indynamically invoke the subclass method
*/
func startAnimation() {
fatalError("This is an abstract function")
}
/**
Every function that extends Indeterminate animation must define **stopAnimation()**.
*animate* property of Indeterminate animation will dynamically invoke the subclass method
*/
func stopAnimation() {
fatalError("This is an abstract function")
}
}
================================================
FILE: InDeterminate/MaterialProgress.swift
================================================
//
// MaterialProgress.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
private let duration = 1.5
private let strokeRange = (start: 0.0, end: 0.8)
@IBDesignable
open class MaterialProgress: IndeterminateAnimation {
@IBInspectable open var lineWidth: CGFloat = -1 {
didSet {
progressLayer.lineWidth = lineWidth
}
}
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
progressLayer.strokeColor = foreground.cgColor
}
var backgroundRotationLayer = CAShapeLayer()
var progressLayer: CAShapeLayer = {
var tempLayer = CAShapeLayer()
tempLayer.strokeEnd = CGFloat(strokeRange.end)
tempLayer.lineCap = .round
tempLayer.fillColor = NSColor.clear.cgColor
return tempLayer
}()
//MARK: Animation Declaration
var animationGroup: CAAnimationGroup = {
var tempGroup = CAAnimationGroup()
tempGroup.repeatCount = 1
tempGroup.duration = duration
return tempGroup
}()
var rotationAnimation: CABasicAnimation = {
var tempRotation = CABasicAnimation(keyPath: "transform.rotation")
tempRotation.repeatCount = Float.infinity
tempRotation.fromValue = 0
tempRotation.toValue = 1
tempRotation.isCumulative = true
tempRotation.duration = duration / 2
return tempRotation
}()
/// Makes animation for Stroke Start and Stroke End
func makeStrokeAnimationGroup() {
var strokeStartAnimation: CABasicAnimation!
var strokeEndAnimation: CABasicAnimation!
func makeAnimationforKeyPath(_ keyPath: String) -> CABasicAnimation {
let tempAnimation = CABasicAnimation(keyPath: keyPath)
tempAnimation.repeatCount = 1
tempAnimation.speed = 2.0
tempAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
tempAnimation.fromValue = strokeRange.start
tempAnimation.toValue = strokeRange.end
tempAnimation.duration = duration
return tempAnimation
}
strokeEndAnimation = makeAnimationforKeyPath("strokeEnd")
strokeStartAnimation = makeAnimationforKeyPath("strokeStart")
strokeStartAnimation.beginTime = duration / 2
animationGroup.animations = [strokeEndAnimation, strokeStartAnimation, ]
animationGroup.delegate = self
}
override func configureLayers() {
super.configureLayers()
makeStrokeAnimationGroup()
let rect = self.bounds
backgroundRotationLayer.frame = rect
self.layer?.addSublayer(backgroundRotationLayer)
// Progress Layer
let radius = (rect.width / 2) * 0.75
progressLayer.frame = rect
progressLayer.lineWidth = lineWidth == -1 ? radius / 10: lineWidth
let arcPath = NSBezierPath()
arcPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360, clockwise: false)
progressLayer.path = arcPath.CGPath
backgroundRotationLayer.addSublayer(progressLayer)
}
var currentRotation = 0.0
let π2 = Double.pi * 2
override func startAnimation() {
progressLayer.add(animationGroup, forKey: "strokeEnd")
backgroundRotationLayer.add(rotationAnimation, forKey: rotationAnimation.keyPath)
}
override func stopAnimation() {
backgroundRotationLayer.removeAllAnimations()
progressLayer.removeAllAnimations()
}
}
extension MaterialProgress: CAAnimationDelegate {
open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if !animate { return }
CATransaction.begin()
CATransaction.setDisableActions(true)
currentRotation += strokeRange.end * π2
currentRotation = currentRotation.truncatingRemainder(dividingBy: π2)
progressLayer.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat( currentRotation)))
CATransaction.commit()
progressLayer.add(animationGroup, forKey: "strokeEnd")
}
}
================================================
FILE: InDeterminate/Rainbow.swift
================================================
//
// Rainbow.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 09/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
@IBDesignable
open class Rainbow: MaterialProgress {
@IBInspectable open var onLightOffDark: Bool = false
override func configureLayers() {
super.configureLayers()
self.background = NSColor.clear
}
override open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
super.animationDidStop(anim, finished: flag)
if onLightOffDark {
progressLayer.strokeColor = lightColorList[Int(arc4random()) % lightColorList.count].cgColor
} else {
progressLayer.strokeColor = darkColorList[Int(arc4random()) % darkColorList.count].cgColor
}
}
}
var randomColor: NSColor {
let red = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0)
let green = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0)
let blue = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0)
return NSColor(calibratedRed: red, green: green, blue: blue, alpha: 1.0)
}
private let lightColorList:[NSColor] = [
NSColor(red: 0.9461, green: 0.6699, blue: 0.6243, alpha: 1.0),
NSColor(red: 0.8625, green: 0.7766, blue: 0.8767, alpha: 1.0),
NSColor(red: 0.6676, green: 0.6871, blue: 0.8313, alpha: 1.0),
NSColor(red: 0.7263, green: 0.6189, blue: 0.8379, alpha: 1.0),
NSColor(red: 0.8912, green: 0.9505, blue: 0.9971, alpha: 1.0),
NSColor(red: 0.7697, green: 0.9356, blue: 0.9692, alpha: 1.0),
NSColor(red: 0.3859, green: 0.7533, blue: 0.9477, alpha: 1.0),
NSColor(red: 0.6435, green: 0.8554, blue: 0.8145, alpha: 1.0),
NSColor(red: 0.8002, green: 0.936, blue: 0.7639, alpha: 1.0),
NSColor(red: 0.5362, green: 0.8703, blue: 0.8345, alpha: 1.0),
NSColor(red: 0.9785, green: 0.8055, blue: 0.4049, alpha: 1.0),
NSColor(red: 1.0, green: 0.8667, blue: 0.6453, alpha: 1.0),
NSColor(red: 0.9681, green: 0.677, blue: 0.2837, alpha: 1.0),
NSColor(red: 0.9898, green: 0.7132, blue: 0.1746, alpha: 1.0),
NSColor(red: 0.8238, green: 0.84, blue: 0.8276, alpha: 1.0),
NSColor(red: 0.8532, green: 0.8763, blue: 0.883, alpha: 1.0),
]
let darkColorList: [NSColor] = [
NSColor(red: 0.9472, green: 0.2496, blue: 0.0488, alpha: 1.0),
NSColor(red: 0.8098, green: 0.1695, blue: 0.0467, alpha: 1.0),
NSColor(red: 0.853, green: 0.2302, blue: 0.3607, alpha: 1.0),
NSColor(red: 0.8152, green: 0.3868, blue: 0.5021, alpha: 1.0),
NSColor(red: 0.96, green: 0.277, blue: 0.3515, alpha: 1.0),
NSColor(red: 0.3686, green: 0.3069, blue: 0.6077, alpha: 1.0),
NSColor(red: 0.5529, green: 0.3198, blue: 0.5409, alpha: 1.0),
NSColor(red: 0.2132, green: 0.4714, blue: 0.7104, alpha: 1.0),
NSColor(red: 0.1706, green: 0.2432, blue: 0.3106, alpha: 1.0),
NSColor(red: 0.195, green: 0.2982, blue: 0.3709, alpha: 1.0),
NSColor(red: 0.0, green: 0.3091, blue: 0.5859, alpha: 1.0),
NSColor(red: 0.2261, green: 0.6065, blue: 0.3403, alpha: 1.0),
NSColor(red: 0.1101, green: 0.5694, blue: 0.4522, alpha: 1.0),
NSColor(red: 0.1716, green: 0.4786, blue: 0.2877, alpha: 1.0),
NSColor(red: 0.8289, green: 0.33, blue: 0.0, alpha: 1.0),
NSColor(red: 0.4183, green: 0.4842, blue: 0.5372, alpha: 1.0),
NSColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0),
]
================================================
FILE: InDeterminate/RotatingArc.swift
================================================
//
// RotatingArc.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 26/10/15.
// Copyright © 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
private let duration = 0.25
@IBDesignable
open class RotatingArc: IndeterminateAnimation {
var backgroundCircle = CAShapeLayer()
var arcLayer = CAShapeLayer()
@IBInspectable open var strokeWidth: CGFloat = 5 {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var arcLength: Int = 35 {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var clockWise: Bool = true {
didSet {
notifyViewRedesigned()
}
}
var radius: CGFloat {
return (self.frame.width / 2) * CGFloat(0.75)
}
var rotationAnimation: CABasicAnimation = {
var tempRotation = CABasicAnimation(keyPath: "transform.rotation")
tempRotation.repeatCount = .infinity
tempRotation.fromValue = 0
tempRotation.toValue = 1
tempRotation.isCumulative = true
tempRotation.duration = duration
return tempRotation
}()
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
arcLayer.strokeColor = foreground.cgColor
backgroundCircle.strokeColor = foreground.withAlphaComponent(0.4).cgColor
backgroundCircle.lineWidth = self.strokeWidth
arcLayer.lineWidth = strokeWidth
rotationAnimation.toValue = clockWise ? -1 : 1
let arcPath = NSBezierPath()
let endAngle: CGFloat = CGFloat(-360) * CGFloat(arcLength) / 100
arcPath.appendArc(withCenter: self.bounds.mid, radius: radius, startAngle: 0, endAngle: endAngle, clockwise: true)
arcLayer.path = arcPath.CGPath
}
override func configureLayers() {
super.configureLayers()
let rect = self.bounds
// Add background Circle
do {
backgroundCircle.frame = rect
backgroundCircle.lineWidth = strokeWidth
backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor
backgroundCircle.fillColor = NSColor.clear.cgColor
let backgroundPath = NSBezierPath()
backgroundPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360)
backgroundCircle.path = backgroundPath.CGPath
self.layer?.addSublayer(backgroundCircle)
}
// Arc Layer
do {
arcLayer.fillColor = NSColor.clear.cgColor
arcLayer.lineWidth = strokeWidth
arcLayer.frame = rect
arcLayer.strokeColor = foreground.cgColor
self.layer?.addSublayer(arcLayer)
}
}
override func startAnimation() {
arcLayer.add(rotationAnimation, forKey: "")
}
override func stopAnimation() {
arcLayer.removeAllAnimations()
}
}
================================================
FILE: InDeterminate/ShootingStars.swift
================================================
//
// ShootingStars.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 09/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
@IBDesignable
open class ShootingStars: IndeterminateAnimation {
fileprivate let animationDuration = 1.0
var starLayer1 = CAShapeLayer()
var starLayer2 = CAShapeLayer()
var animation = CABasicAnimation(keyPath: "position.x")
var tempAnimation = CABasicAnimation(keyPath: "position.x")
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
starLayer1.backgroundColor = foreground.cgColor
starLayer2.backgroundColor = foreground.cgColor
}
override func configureLayers() {
super.configureLayers()
let rect = self.bounds
let dimension = rect.height
let starWidth = dimension * 1.5
self.layer?.cornerRadius = 0
/// Add Stars
do {
starLayer1.position = CGPoint(x: dimension / 2, y: dimension / 2)
starLayer1.bounds.size = CGSize(width: starWidth, height: dimension)
starLayer1.backgroundColor = foreground.cgColor
self.layer?.addSublayer(starLayer1)
starLayer2.position = CGPoint(x: rect.midX, y: dimension / 2)
starLayer2.bounds.size = CGSize(width: starWidth, height: dimension)
starLayer2.backgroundColor = foreground.cgColor
self.layer?.addSublayer(starLayer2)
}
/// Add default animation
do {
animation.fromValue = -dimension
animation.toValue = rect.width * 0.9
animation.duration = animationDuration
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
animation.isRemovedOnCompletion = false
animation.repeatCount = .infinity
}
/** Temp animation will be removed after first animation
After finishing it will invoke animationDidStop and starLayer2 is also given default animation.
The purpose of temp animation is to generate an temporary offset
*/
tempAnimation.fromValue = rect.midX
tempAnimation.toValue = rect.width
tempAnimation.delegate = self
tempAnimation.duration = animationDuration / 2
tempAnimation.timingFunction = CAMediaTimingFunction(name: .easeIn)
}
//MARK: Indeterminable protocol
override func startAnimation() {
starLayer1.add(animation, forKey: "default")
starLayer2.add(tempAnimation, forKey: "tempAnimation")
}
override func stopAnimation() {
starLayer1.removeAllAnimations()
starLayer2.removeAllAnimations()
}
}
extension ShootingStars: CAAnimationDelegate {
open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
starLayer2.add(animation, forKey: "default")
}
}
================================================
FILE: InDeterminate/Spinner.swift
================================================
//
// Spinner.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 28/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
@IBDesignable
open class Spinner: IndeterminateAnimation {
var basicShape = CAShapeLayer()
var containerLayer = CAShapeLayer()
var starList = [CAShapeLayer]()
var animation: CAKeyframeAnimation = {
var animation = CAKeyframeAnimation(keyPath: "transform.rotation")
animation.repeatCount = .infinity
animation.calculationMode = .discrete
return animation
}()
@IBInspectable open var starSize:CGSize = CGSize(width: 6, height: 15) {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var roundedCorners: Bool = true {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var distance: CGFloat = CGFloat(20) {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var starCount: Int = 10 {
didSet {
notifyViewRedesigned()
}
}
@IBInspectable open var duration: Double = 1 {
didSet {
animation.duration = duration
}
}
@IBInspectable open var clockwise: Bool = false {
didSet {
notifyViewRedesigned()
}
}
override func configureLayers() {
super.configureLayers()
containerLayer.frame = self.bounds
containerLayer.cornerRadius = frame.width / 2
self.layer?.addSublayer(containerLayer)
animation.duration = duration
}
override func notifyViewRedesigned() {
super.notifyViewRedesigned()
starList.removeAll(keepingCapacity: true)
containerLayer.sublayers = nil
animation.values = [Double]()
var i = 0.0
while i < 360 {
var iRadian = CGFloat(i * Double.pi / 180.0)
if clockwise { iRadian = -iRadian }
animation.values?.append(iRadian)
let starShape = CAShapeLayer()
starShape.cornerRadius = roundedCorners ? starSize.width / 2 : 0
let centerLocation = CGPoint(x: frame.width / 2 - starSize.width / 2, y: frame.width / 2 - starSize.height / 2)
starShape.frame = CGRect(origin: centerLocation, size: starSize)
starShape.backgroundColor = foreground.cgColor
starShape.anchorPoint = CGPoint(x: 0.5, y: 0)
var rotation: CATransform3D = CATransform3DMakeTranslation(0, 0, 0.0);
rotation = CATransform3DRotate(rotation, -iRadian, 0.0, 0.0, 1.0);
rotation = CATransform3DTranslate(rotation, 0, distance, 0.0);
starShape.transform = rotation
starShape.opacity = Float(360 - i) / 360
containerLayer.addSublayer(starShape)
starList.append(starShape)
i = i + Double(360 / starCount)
}
}
override func startAnimation() {
containerLayer.add(animation, forKey: "rotation")
}
override func stopAnimation() {
containerLayer.removeAllAnimations()
}
}
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 Kaunteya Suryawanshi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: ProgressKit/AppDelegate.swift
================================================
//
// AppDelegate.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
================================================
FILE: ProgressKit/Base.lproj/Main.storyboard
================================================
================================================
FILE: ProgressKit/Determinate.swift
================================================
//
// ViewController.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Cocoa
class DeterminateViewController: NSViewController {
dynamic var liveProgress: Bool = true
dynamic var labelPercentage: String = "30%"
@IBOutlet weak var circularView1: CircularProgressView!
@IBOutlet weak var circularView2: CircularProgressView!
@IBOutlet weak var circularView3: CircularProgressView!
@IBOutlet weak var circularView4: CircularProgressView!
@IBOutlet weak var circularView5: CircularProgressView!
@IBOutlet weak var slider: NSSlider!
@IBAction func sliderDragged(sender: NSSlider) {
let event = NSApplication.sharedApplication().currentEvent
let dragStart = event!.type == NSEventType.LeftMouseDown
let dragEnd = event!.type == NSEventType.LeftMouseUp
let dragging = event!.type == NSEventType.LeftMouseDragged
if liveProgress || dragEnd {
setProgress(CGFloat(sender.floatValue))
}
labelPercentage = "\(Int(sender.floatValue * 100))%"
}
func setProgress(progress: CGFloat) {
circularView1.setProgressValue(progress, animated: true)
circularView2.setProgressValue(progress, animated: true)
circularView3.setProgressValue(progress, animated: true)
circularView4.setProgressValue(progress, animated: true)
circularView5.setProgressValue(progress, animated: false)
}
override func viewDidLoad() {
preferredContentSize = NSMakeSize(500, 500)
}
}
================================================
FILE: ProgressKit/DeterminateVC.swift
================================================
//
// ViewController.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Cocoa
class DeterminateViewController: NSViewController {
@objc dynamic var liveProgress: Bool = true
@objc dynamic var labelPercentage: String = "30%"
override func viewDidLoad() {
preferredContentSize = NSMakeSize(500, 300)
}
@IBOutlet weak var slider: NSSlider!
@IBAction func sliderDragged(_ sender: NSSlider) {
let event = NSApplication.shared.currentEvent
// let dragStart = event!.type == NSEventType.LeftMouseDown
let dragEnd = event!.type == NSEvent.EventType.leftMouseUp
// let dragging = event!.type == NSEventType.LeftMouseDragged
if liveProgress || dragEnd {
setProgress(CGFloat(sender.floatValue))
}
labelPercentage = "\(Int(sender.floatValue * 100))%"
}
func setProgress(_ progress: CGFloat) {
for view in self.view.subviews {
if view is DeterminateAnimation {
(view as! DeterminateAnimation).progress = progress
}
}
}
}
================================================
FILE: ProgressKit/InDeterminate.swift
================================================
//
// WhatsAppCircular.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
class InDeterminateViewController: NSViewController {
@IBOutlet weak var doing1: DoingCircular!
@IBOutlet weak var doing2: DoingCircular!
@IBOutlet weak var doing3: DoingCircular!
@IBOutlet weak var doing4: DoingCircular!
override func viewDidLoad() {
preferredContentSize = NSMakeSize(500, 500)
}
@IBAction func startStopAnimation(sender: NSButton) {
let isOn = sender.state == NSOnState
doing1.animate = isOn
doing2.animate = isOn
doing3.animate = isOn
doing4.animate = isOn
}
}
================================================
FILE: ProgressKit/InDeterminateVC.swift
================================================
//
// WhatsAppCircular.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Foundation
import Cocoa
class InDeterminateViewController: NSViewController {
override func viewDidAppear() {
for view in self.view.subviews {
(view as? IndeterminateAnimation)?.animate = true
}
}
override func viewWillDisappear() {
for view in self.view.subviews {
(view as? IndeterminateAnimation)?.animate = false
}
}
}
================================================
FILE: ProgressKit/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIconFile
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
NSHumanReadableCopyright
Copyright © 2015 Kauntey Suryawanshi. All rights reserved.
NSMainStoryboardFile
Main
NSPrincipalClass
NSApplication
================================================
FILE: ProgressKit.podspec
================================================
Pod::Spec.new do |spec|
spec.name = 'ProgressKit'
spec.version = '0.8'
spec.license = 'MIT'
spec.summary = 'Animated ProgressViews for macOS'
spec.homepage = 'https://github.com/kaunteya/ProgressKit'
spec.authors = { 'Kaunteya Suryawanshi' => 'k.suryawanshi@gmail.com' }
spec.source = { :git => 'https://github.com/kaunteya/ProgressKit.git', :tag => spec.version }
spec.platform = :osx, '10.10'
spec.requires_arc = true
spec.source_files = 'Determinate/*.swift', 'InDeterminate/*.swift', 'ProgressUtils.swift', 'BaseView.swift'
end
================================================
FILE: ProgressKit.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
E31617A61BC0596C007AD70F /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E31617A51BC0596C007AD70F /* BaseView.swift */; };
E340FDB81BDE45F000CE6550 /* RotatingArc.swift in Sources */ = {isa = PBXBuildFile; fileRef = E340FDB71BDE45F000CE6550 /* RotatingArc.swift */; };
E35D1C6C1B676889001DBAF2 /* Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35D1C6B1B676889001DBAF2 /* Spinner.swift */; };
E37568DF1B6AAB530073E26F /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37568DE1B6AAB530073E26F /* ProgressBar.swift */; };
E3918F811B4E88CF00558DAB /* CircularProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F801B4E88CF00558DAB /* CircularProgressView.swift */; };
E3918F841B4E88DE00558DAB /* MaterialProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F821B4E88DE00558DAB /* MaterialProgress.swift */; };
E3918F851B4E88DE00558DAB /* ShootingStars.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F831B4E88DE00558DAB /* ShootingStars.swift */; };
E3918F8D1B4E8AB100558DAB /* IndeterminateAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */; };
E3918F8F1B4E8C2900558DAB /* DeterminateAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */; };
E3918FA81B4ECF7100558DAB /* Rainbow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918FA71B4ECF7100558DAB /* Rainbow.swift */; };
E3A468521B5434F7006DDE31 /* Crawler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A468511B5434F7006DDE31 /* Crawler.swift */; };
E3AD65D81B426758009541CD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65D71B426758009541CD /* AppDelegate.swift */; };
E3AD65DA1B426758009541CD /* DeterminateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65D91B426758009541CD /* DeterminateVC.swift */; };
E3AD65DF1B426758009541CD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3AD65DD1B426758009541CD /* Main.storyboard */; };
E3AD65EB1B426758009541CD /* ProgressKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65EA1B426758009541CD /* ProgressKitTests.swift */; };
E3AD65F71B427511009541CD /* InDeterminateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65F61B427511009541CD /* InDeterminateVC.swift */; };
E3CCD59A1BBC2B9B00F7DB9A /* ProgressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
E3AD65E51B426758009541CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E3AD65CA1B426758009541CD /* Project object */;
proxyType = 1;
remoteGlobalIDString = E3AD65D11B426758009541CD;
remoteInfo = ProgressKit;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
E310B1D21D7AB2D4008DEF62 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
E310B1D41D7AB2EA008DEF62 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; };
E31617A51BC0596C007AD70F /* BaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = ""; };
E340FDB71BDE45F000CE6550 /* RotatingArc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RotatingArc.swift; path = InDeterminate/RotatingArc.swift; sourceTree = ""; };
E35D1C6B1B676889001DBAF2 /* Spinner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Spinner.swift; path = InDeterminate/Spinner.swift; sourceTree = ""; };
E37568DE1B6AAB530073E26F /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProgressBar.swift; path = Determinate/ProgressBar.swift; sourceTree = ""; };
E3918F801B4E88CF00558DAB /* CircularProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CircularProgressView.swift; path = Determinate/CircularProgressView.swift; sourceTree = ""; };
E3918F821B4E88DE00558DAB /* MaterialProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MaterialProgress.swift; path = InDeterminate/MaterialProgress.swift; sourceTree = ""; };
E3918F831B4E88DE00558DAB /* ShootingStars.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShootingStars.swift; path = InDeterminate/ShootingStars.swift; sourceTree = ""; };
E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IndeterminateAnimation.swift; path = InDeterminate/IndeterminateAnimation.swift; sourceTree = ""; };
E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DeterminateAnimation.swift; path = Determinate/DeterminateAnimation.swift; sourceTree = ""; };
E3918FA71B4ECF7100558DAB /* Rainbow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Rainbow.swift; path = InDeterminate/Rainbow.swift; sourceTree = ""; };
E3A468511B5434F7006DDE31 /* Crawler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Crawler.swift; path = InDeterminate/Crawler.swift; sourceTree = ""; };
E3AD65D21B426758009541CD /* ProgressKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProgressKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
E3AD65D61B426758009541CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
E3AD65D71B426758009541CD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
E3AD65D91B426758009541CD /* DeterminateVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeterminateVC.swift; sourceTree = ""; };
E3AD65DE1B426758009541CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
E3AD65E41B426758009541CD /* ProgressKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProgressKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
E3AD65E91B426758009541CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
E3AD65EA1B426758009541CD /* ProgressKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressKitTests.swift; sourceTree = ""; };
E3AD65F61B427511009541CD /* InDeterminateVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InDeterminateVC.swift; sourceTree = ""; };
E3CCD5971BBC19ED00F7DB9A /* ProgressKit.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ProgressKit.podspec; sourceTree = SOURCE_ROOT; };
E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressUtils.swift; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E3AD65CF1B426758009541CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E3AD65E11B426758009541CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E316CCAA1B4E8633005A9A31 /* Indeterminate */ = {
isa = PBXGroup;
children = (
E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */,
E3918F821B4E88DE00558DAB /* MaterialProgress.swift */,
E3918FA71B4ECF7100558DAB /* Rainbow.swift */,
E3A468511B5434F7006DDE31 /* Crawler.swift */,
E3918F831B4E88DE00558DAB /* ShootingStars.swift */,
E35D1C6B1B676889001DBAF2 /* Spinner.swift */,
E340FDB71BDE45F000CE6550 /* RotatingArc.swift */,
);
name = Indeterminate;
sourceTree = "";
};
E316CCAB1B4E8642005A9A31 /* Determinate */ = {
isa = PBXGroup;
children = (
E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */,
E3918F801B4E88CF00558DAB /* CircularProgressView.swift */,
E37568DE1B6AAB530073E26F /* ProgressBar.swift */,
);
name = Determinate;
sourceTree = "";
};
E3AD65C91B426758009541CD = {
isa = PBXGroup;
children = (
E31617A51BC0596C007AD70F /* BaseView.swift */,
E316CCAA1B4E8633005A9A31 /* Indeterminate */,
E316CCAB1B4E8642005A9A31 /* Determinate */,
E3AD65D41B426758009541CD /* ProgressKit */,
E3AD65E71B426758009541CD /* ProgressKitTests */,
E3AD65D31B426758009541CD /* Products */,
);
sourceTree = "";
};
E3AD65D31B426758009541CD /* Products */ = {
isa = PBXGroup;
children = (
E3AD65D21B426758009541CD /* ProgressKit.app */,
E3AD65E41B426758009541CD /* ProgressKitTests.xctest */,
);
name = Products;
sourceTree = "";
};
E3AD65D41B426758009541CD /* ProgressKit */ = {
isa = PBXGroup;
children = (
E3AD65D71B426758009541CD /* AppDelegate.swift */,
E3AD65D91B426758009541CD /* DeterminateVC.swift */,
E3AD65F61B427511009541CD /* InDeterminateVC.swift */,
E3AD65DD1B426758009541CD /* Main.storyboard */,
E3AD65D51B426758009541CD /* Supporting Files */,
);
path = ProgressKit;
sourceTree = "";
};
E3AD65D51B426758009541CD /* Supporting Files */ = {
isa = PBXGroup;
children = (
E310B1D21D7AB2D4008DEF62 /* README.md */,
E310B1D41D7AB2EA008DEF62 /* LICENSE */,
E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */,
E3CCD5971BBC19ED00F7DB9A /* ProgressKit.podspec */,
E3AD65D61B426758009541CD /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
E3AD65E71B426758009541CD /* ProgressKitTests */ = {
isa = PBXGroup;
children = (
E3AD65EA1B426758009541CD /* ProgressKitTests.swift */,
E3AD65E81B426758009541CD /* Supporting Files */,
);
path = ProgressKitTests;
sourceTree = "";
};
E3AD65E81B426758009541CD /* Supporting Files */ = {
isa = PBXGroup;
children = (
E3AD65E91B426758009541CD /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E3AD65D11B426758009541CD /* ProgressKit */ = {
isa = PBXNativeTarget;
buildConfigurationList = E3AD65EE1B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKit" */;
buildPhases = (
E3AD65CE1B426758009541CD /* Sources */,
E3AD65CF1B426758009541CD /* Frameworks */,
E3AD65D01B426758009541CD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ProgressKit;
productName = ProgressKit;
productReference = E3AD65D21B426758009541CD /* ProgressKit.app */;
productType = "com.apple.product-type.application";
};
E3AD65E31B426758009541CD /* ProgressKitTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = E3AD65F11B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKitTests" */;
buildPhases = (
E3AD65E01B426758009541CD /* Sources */,
E3AD65E11B426758009541CD /* Frameworks */,
E3AD65E21B426758009541CD /* Resources */,
);
buildRules = (
);
dependencies = (
E3AD65E61B426758009541CD /* PBXTargetDependency */,
);
name = ProgressKitTests;
productName = ProgressKitTests;
productReference = E3AD65E41B426758009541CD /* ProgressKitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E3AD65CA1B426758009541CD /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = "Kauntey Suryawanshi";
TargetAttributes = {
E3AD65D11B426758009541CD = {
CreatedOnToolsVersion = 6.3.2;
LastSwiftMigration = 0920;
};
E3AD65E31B426758009541CD = {
CreatedOnToolsVersion = 6.3.2;
LastSwiftMigration = 0920;
TestTargetID = E3AD65D11B426758009541CD;
};
};
};
buildConfigurationList = E3AD65CD1B426758009541CD /* Build configuration list for PBXProject "ProgressKit" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E3AD65C91B426758009541CD;
productRefGroup = E3AD65D31B426758009541CD /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E3AD65D11B426758009541CD /* ProgressKit */,
E3AD65E31B426758009541CD /* ProgressKitTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E3AD65D01B426758009541CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E3AD65DF1B426758009541CD /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E3AD65E21B426758009541CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E3AD65CE1B426758009541CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E3A468521B5434F7006DDE31 /* Crawler.swift in Sources */,
E3AD65DA1B426758009541CD /* DeterminateVC.swift in Sources */,
E3918F8D1B4E8AB100558DAB /* IndeterminateAnimation.swift in Sources */,
E3AD65F71B427511009541CD /* InDeterminateVC.swift in Sources */,
E3918F851B4E88DE00558DAB /* ShootingStars.swift in Sources */,
E3918F811B4E88CF00558DAB /* CircularProgressView.swift in Sources */,
E35D1C6C1B676889001DBAF2 /* Spinner.swift in Sources */,
E3918F841B4E88DE00558DAB /* MaterialProgress.swift in Sources */,
E3AD65D81B426758009541CD /* AppDelegate.swift in Sources */,
E37568DF1B6AAB530073E26F /* ProgressBar.swift in Sources */,
E340FDB81BDE45F000CE6550 /* RotatingArc.swift in Sources */,
E3CCD59A1BBC2B9B00F7DB9A /* ProgressUtils.swift in Sources */,
E31617A61BC0596C007AD70F /* BaseView.swift in Sources */,
E3918FA81B4ECF7100558DAB /* Rainbow.swift in Sources */,
E3918F8F1B4E8C2900558DAB /* DeterminateAnimation.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E3AD65E01B426758009541CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E3AD65EB1B426758009541CD /* ProgressKitTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E3AD65E61B426758009541CD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E3AD65D11B426758009541CD /* ProgressKit */;
targetProxy = E3AD65E51B426758009541CD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
E3AD65DD1B426758009541CD /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E3AD65DE1B426758009541CD /* Base */,
);
name = Main.storyboard;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
E3AD65EC1B426758009541CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
E3AD65ED1B426758009541CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
};
name = Release;
};
E3AD65EF1B426758009541CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = ProgressKit/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
E3AD65F01B426758009541CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = ProgressKit/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
};
name = Release;
};
E3AD65F21B426758009541CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ProgressKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ProgressKit.app/Contents/MacOS/ProgressKit";
};
name = Debug;
};
E3AD65F31B426758009541CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
INFOPLIST_FILE = ProgressKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ProgressKit.app/Contents/MacOS/ProgressKit";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E3AD65CD1B426758009541CD /* Build configuration list for PBXProject "ProgressKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E3AD65EC1B426758009541CD /* Debug */,
E3AD65ED1B426758009541CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E3AD65EE1B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E3AD65EF1B426758009541CD /* Debug */,
E3AD65F01B426758009541CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E3AD65F11B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKitTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E3AD65F21B426758009541CD /* Debug */,
E3AD65F31B426758009541CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E3AD65CA1B426758009541CD /* Project object */;
}
================================================
FILE: ProgressKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: ProgressKitTests/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: ProgressKitTests/ProgressKitTests.swift
================================================
//
// ProgressKitTests.swift
// ProgressKitTests
//
// Created by Kauntey Suryawanshi on 30/06/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import Cocoa
import XCTest
class ProgressKitTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
}
}
================================================
FILE: ProgressUtils.swift
================================================
//
// ProgressUtils.swift
// ProgressKit
//
// Created by Kauntey Suryawanshi on 09/07/15.
// Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved.
//
import AppKit
extension NSRect {
var mid: CGPoint {
return CGPoint(x: self.midX, y: self.midY)
}
}
extension NSBezierPath {
/// Converts NSBezierPath to CGPath
var CGPath: CGPath {
let path = CGMutablePath()
let points = UnsafeMutablePointer.allocate(capacity: 3)
let numElements = self.elementCount
for index in 0.. Double {
return Double(degree) * (Double.pi / 180)
}
func radianToDegree(_ radian: Double) -> Int {
return Int(radian * (180 / Double.pi))
}
func + (p1: CGPoint, p2: CGPoint) -> CGPoint {
return CGPoint(x: p1.x + p2.x, y: p1.y + p2.y)
}
================================================
FILE: README.md
================================================

[](https://img.shields.io/cocoapods/v/ProgressKit.svg)
[](http://cocoadocs.org/docsets/ProgressKit)
[](http://cocoadocs.org/docsets/ProgressKit)
`ProgressKit` has set of cool `IBDesignable` progress views, with huge customisation options.
You can now make spinners, progress bar, crawlers etc, which can be finely customised according to your app palette.
# Contents
- [Installation](#installation)
- [Usage](#usage)
- [Indeterminate Progress](#indeterminate-progress)
- [MaterialProgress](#MaterialProgress)
- [Rainbow](#rainbow)
- [Crawler](#crawler)
- [Spinner](#spinner)
- [Shooting Stars](#shooting-stars)
- [Rotating Arc](#rotating-arc)
- [Determinate Progress](#determinate-progress)
- [Circular Progress](#circular-progress)
- [Progress Bar](#progress-bar)
- [Other Apps](#other-apps)
- [License](#license)
# Installation
##CocoaPods
[CocoaPods](http://cocoapods.org) adds supports for Swift and embedded frameworks.
To integrate ProgressKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
use_frameworks!
pod 'ProgressKit'
```
For Swift 3 install directly from `swift-3` branch form github
```ruby
pod 'ProgressKit', :git => "https://github.com/kaunteya/ProgressKit.git", :branch => 'swift-3'
```
Then, run the following command:
```bash
$ pod install
```
# Usage
- Drag a View at desired location in `XIB` or `Storyboard`
- Change the Class to any of the desired progress views
- Set the size such that width and height are equal
- Drag `IBOutlet` to View Controller
- For `Indeterminate` Progress Views
- Set `true / false` to `view.animate`
- For `Determinate` Progress Views:
- Set `view.progress` to value in `0...1`
# Indeterminate Progress

Progress indicators which animate indefinately are `Indeterminate Progress` Views.
This are the set of Indeterminate Progress Indicators.
## MaterialProgress

## Rainbow

## Crawler

## Spinner

## Shooting Stars

## Rotating Arc

# Determinate Progress
Determinate progress views can be used for tasks whos progress can be seen and determined.
## Circular Progress

## Progress Bar

# Other Apps for Mac
Apart from making Open source libraries I also make apps for Mac OS. Please have a look.
## [Lexi](https://apps.apple.com/tr/app/lexi-visual-json-browser/id1462580127?mt=12)
Lexi is a split screen app that lets you browse large JSON with ease.
It also has other featuers like `Prettify JSON`, `Minify JSON` `Copy JSON Path` and `Pin Large JSON` to narrow your visibility
[View on Mac AppStore](https://apps.apple.com/tr/app/lexi-visual-json-browser/id1462580127?mt=12)
## [Quick Note](https://apps.apple.com/in/app/quicknote-one-click-notes/id1472935217?mt=12)
Quick Note is a Mac OS app, lets you quickly add text either from Menu bar or from Shortcut.
The text floats on other windows so that they are always visible
It also supports `Auto Save` and `Pinned Notes`
[View on Mac AppStore](https://apps.apple.com/in/app/quicknote-one-click-notes/id1472935217?mt=12)
# License
`ProgressKit` is released under the MIT license. See LICENSE for details.