2019-07-16 14:25:09 -07:00
|
|
|
//
|
2019-07-19 16:42:40 -07:00
|
|
|
// PillButton.swift
|
2019-07-16 14:25:09 -07:00
|
|
|
// AltStore
|
|
|
|
|
//
|
|
|
|
|
// Created by Riley Testut on 7/15/19.
|
|
|
|
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
2023-04-04 15:44:29 -05:00
|
|
|
extension PillButton
|
|
|
|
|
{
|
|
|
|
|
static let minimumSize = CGSize(width: 77, height: 31)
|
|
|
|
|
static let contentInsets = NSDirectionalEdgeInsets(top: 7, leading: 13, bottom: 7, trailing: 13)
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-04 09:52:12 -05:00
|
|
|
final class PillButton: UIButton
|
2019-07-16 14:25:09 -07:00
|
|
|
{
|
2020-08-27 15:23:21 -07:00
|
|
|
override var accessibilityValue: String? {
|
|
|
|
|
get {
|
|
|
|
|
guard self.progress != nil else { return super.accessibilityValue }
|
|
|
|
|
return self.progressView.accessibilityValue
|
|
|
|
|
}
|
|
|
|
|
set { super.accessibilityValue = newValue }
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 14:25:09 -07:00
|
|
|
var progress: Progress? {
|
2019-10-23 14:20:01 -07:00
|
|
|
didSet {
|
2019-07-16 14:25:09 -07:00
|
|
|
self.progressView.progress = Float(self.progress?.fractionCompleted ?? 0)
|
|
|
|
|
self.progressView.observedProgress = self.progress
|
2019-07-19 16:42:40 -07:00
|
|
|
|
|
|
|
|
let isUserInteractionEnabled = self.isUserInteractionEnabled
|
|
|
|
|
self.isIndicatingActivity = (self.progress != nil)
|
|
|
|
|
self.isUserInteractionEnabled = isUserInteractionEnabled
|
2019-10-23 14:20:01 -07:00
|
|
|
|
|
|
|
|
self.update()
|
2019-07-16 14:25:09 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var progressTintColor: UIColor? {
|
|
|
|
|
get {
|
|
|
|
|
return self.progressView.progressTintColor
|
|
|
|
|
}
|
|
|
|
|
set {
|
|
|
|
|
self.progressView.progressTintColor = newValue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-07 15:37:08 -07:00
|
|
|
var countdownDate: Date? {
|
|
|
|
|
didSet {
|
|
|
|
|
self.isEnabled = (self.countdownDate == nil)
|
|
|
|
|
self.displayLink.isPaused = (self.countdownDate == nil)
|
|
|
|
|
|
|
|
|
|
if self.countdownDate == nil
|
|
|
|
|
{
|
|
|
|
|
self.setTitle(nil, for: .disabled)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 14:25:09 -07:00
|
|
|
private let progressView = UIProgressView(progressViewStyle: .default)
|
|
|
|
|
|
2019-09-07 15:37:08 -07:00
|
|
|
private lazy var displayLink: CADisplayLink = {
|
|
|
|
|
let displayLink = CADisplayLink(target: self, selector: #selector(PillButton.updateCountdown))
|
|
|
|
|
displayLink.preferredFramesPerSecond = 15
|
|
|
|
|
displayLink.isPaused = true
|
|
|
|
|
displayLink.add(to: .main, forMode: .common)
|
|
|
|
|
return displayLink
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
private let dateComponentsFormatter: DateComponentsFormatter = {
|
|
|
|
|
let dateComponentsFormatter = DateComponentsFormatter()
|
|
|
|
|
dateComponentsFormatter.zeroFormattingBehavior = [.pad]
|
|
|
|
|
dateComponentsFormatter.collapsesLargestUnit = false
|
|
|
|
|
return dateComponentsFormatter
|
|
|
|
|
}()
|
|
|
|
|
|
2019-07-16 14:25:09 -07:00
|
|
|
override var intrinsicContentSize: CGSize {
|
2023-04-04 15:44:29 -05:00
|
|
|
let size = self.sizeThatFits(CGSize(width: Double.infinity, height: .infinity))
|
2019-07-16 14:25:09 -07:00
|
|
|
return size
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-07 15:37:08 -07:00
|
|
|
deinit
|
|
|
|
|
{
|
|
|
|
|
self.displayLink.remove(from: .main, forMode: RunLoop.Mode.default)
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 14:25:09 -07:00
|
|
|
override func awakeFromNib()
|
|
|
|
|
{
|
|
|
|
|
super.awakeFromNib()
|
|
|
|
|
|
|
|
|
|
self.layer.masksToBounds = true
|
2020-08-27 15:23:21 -07:00
|
|
|
self.accessibilityTraits.formUnion([.updatesFrequently, .button])
|
2019-07-16 14:25:09 -07:00
|
|
|
|
2023-04-04 15:44:29 -05:00
|
|
|
self.contentEdgeInsets = UIEdgeInsets(top: Self.contentInsets.top, left: Self.contentInsets.leading, bottom: Self.contentInsets.bottom, right: Self.contentInsets.trailing)
|
|
|
|
|
|
2022-12-17 03:13:30 -05:00
|
|
|
self.activityIndicatorView.style = .medium
|
2023-03-02 14:48:20 -06:00
|
|
|
self.activityIndicatorView.color = .white
|
2019-07-19 16:42:40 -07:00
|
|
|
self.activityIndicatorView.isUserInteractionEnabled = false
|
|
|
|
|
|
2019-07-16 14:25:09 -07:00
|
|
|
self.progressView.progress = 0
|
|
|
|
|
self.progressView.trackImage = UIImage()
|
|
|
|
|
self.progressView.isUserInteractionEnabled = false
|
|
|
|
|
self.addSubview(self.progressView)
|
2019-07-19 16:42:40 -07:00
|
|
|
|
|
|
|
|
self.update()
|
2019-07-16 14:25:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func layoutSubviews()
|
|
|
|
|
{
|
|
|
|
|
super.layoutSubviews()
|
|
|
|
|
|
|
|
|
|
self.progressView.bounds.size.width = self.bounds.width
|
|
|
|
|
|
|
|
|
|
let scale = self.bounds.height / self.progressView.bounds.height
|
|
|
|
|
|
|
|
|
|
self.progressView.transform = CGAffineTransform.identity.scaledBy(x: 1, y: scale)
|
|
|
|
|
self.progressView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
|
|
|
|
|
|
|
|
|
|
self.layer.cornerRadius = self.bounds.midY
|
|
|
|
|
}
|
2019-07-19 16:42:40 -07:00
|
|
|
|
|
|
|
|
override func tintColorDidChange()
|
|
|
|
|
{
|
|
|
|
|
super.tintColorDidChange()
|
|
|
|
|
|
|
|
|
|
self.update()
|
|
|
|
|
}
|
2023-04-04 15:44:29 -05:00
|
|
|
|
|
|
|
|
override func sizeThatFits(_ size: CGSize) -> CGSize
|
|
|
|
|
{
|
|
|
|
|
var size = super.sizeThatFits(size)
|
|
|
|
|
size.width = max(size.width, PillButton.minimumSize.width)
|
|
|
|
|
size.height = max(size.height, PillButton.minimumSize.height)
|
|
|
|
|
|
|
|
|
|
return size
|
|
|
|
|
}
|
2019-07-19 16:42:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension PillButton
|
|
|
|
|
{
|
|
|
|
|
func update()
|
|
|
|
|
{
|
2019-10-23 14:20:01 -07:00
|
|
|
if self.progress == nil
|
2019-07-19 16:42:40 -07:00
|
|
|
{
|
|
|
|
|
self.setTitleColor(.white, for: .normal)
|
|
|
|
|
self.backgroundColor = self.tintColor
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self.setTitleColor(self.tintColor, for: .normal)
|
|
|
|
|
self.backgroundColor = self.tintColor.withAlphaComponent(0.15)
|
|
|
|
|
}
|
2019-10-23 14:20:01 -07:00
|
|
|
|
|
|
|
|
self.progressView.progressTintColor = self.tintColor
|
2019-07-19 16:42:40 -07:00
|
|
|
}
|
2019-09-07 15:37:08 -07:00
|
|
|
|
|
|
|
|
@objc func updateCountdown()
|
|
|
|
|
{
|
|
|
|
|
guard let endDate = self.countdownDate else { return }
|
|
|
|
|
|
|
|
|
|
let startDate = Date()
|
|
|
|
|
|
|
|
|
|
let interval = endDate.timeIntervalSince(startDate)
|
|
|
|
|
guard interval > 0 else {
|
|
|
|
|
self.isEnabled = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let text: String?
|
|
|
|
|
|
|
|
|
|
if interval < (1 * 60 * 60)
|
|
|
|
|
{
|
|
|
|
|
self.dateComponentsFormatter.unitsStyle = .positional
|
|
|
|
|
self.dateComponentsFormatter.allowedUnits = [.minute, .second]
|
|
|
|
|
|
|
|
|
|
text = self.dateComponentsFormatter.string(from: startDate, to: endDate)
|
|
|
|
|
}
|
|
|
|
|
else if interval < (2 * 24 * 60 * 60)
|
|
|
|
|
{
|
|
|
|
|
self.dateComponentsFormatter.unitsStyle = .positional
|
|
|
|
|
self.dateComponentsFormatter.allowedUnits = [.hour, .minute, .second]
|
|
|
|
|
|
|
|
|
|
text = self.dateComponentsFormatter.string(from: startDate, to: endDate)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self.dateComponentsFormatter.unitsStyle = .full
|
|
|
|
|
self.dateComponentsFormatter.allowedUnits = [.day]
|
|
|
|
|
|
|
|
|
|
let numberOfDays = endDate.numberOfCalendarDays(since: startDate)
|
|
|
|
|
text = String(format: NSLocalizedString("%@ DAYS", comment: ""), NSNumber(value: numberOfDays))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let text = text
|
|
|
|
|
{
|
|
|
|
|
UIView.performWithoutAnimation {
|
|
|
|
|
self.isEnabled = false
|
|
|
|
|
self.setTitle(text, for: .disabled)
|
|
|
|
|
self.layoutIfNeeded()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self.isEnabled = true
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-16 14:25:09 -07:00
|
|
|
}
|