Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/production safety #62

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions Sources/ShowTime/ShowTime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ public final class ShowTime: NSObject {
}

/// Whether ShowTime is enabled.
/// ShowTime automatically enables itself by default.
/// (`.always` by default)
@objc public static var enabled: Enabled = .always
/// ShowTime automatically disabled by default.
/// (`.never` by default)
@objc public static var enabled: Enabled = .never

/// The fill (background) colour of the visual touches.
/// If set to `.auto`, ShowTime automatically uses the stroke color with 50% alpha.
/// (`.auto` by default)
Expand All @@ -49,10 +49,10 @@ public final class ShowTime: NSObject {
/// (3pt by default)
@objc public static var strokeWidth: CGFloat = 3

/// The size of the touch circles.
/// The diametr of the touch circles.
/// (44pt x 44pt by default)
@objc public static var size = CGSize(width: 44, height: 44) // TODO: Just make CGFloat
@objc public static var size: CGFloat = 44

/// The style of animation to use when hiding a visual touch.
/// (`.standard` by default)
public static var disappearAnimation: Animation = .standard
Expand Down Expand Up @@ -112,10 +112,10 @@ class TouchView: UILabel {
/// - view: A view the touch is relative to, typically the window calling `sendEvent(_:)`.
convenience init(touch: UITouch, relativeTo view: UIView) {
let location = touch.location(in: view)
self.init(frame: CGRect(x: location.x - ShowTime.size.width / 2,
y: location.y - ShowTime.size.height / 2,
width: ShowTime.size.width,
height: ShowTime.size.height))
self.init(frame: CGRect(x: location.x - ShowTime.size / 2,
y: location.y - ShowTime.size / 2,
width: ShowTime.size,
height: ShowTime.size))
style(with: touch)
}

Expand All @@ -126,7 +126,7 @@ class TouchView: UILabel {
/// - view: A view the touch is relative to, typically the window calling `sendEvent(_:)`.
func update(with touch: UITouch, relativeTo view: UIView) {
let location = touch.location(in: view)
frame = CGRect(x: location.x - ShowTime.size.width / 2, y: location.y - ShowTime.size.height / 2, width: ShowTime.size.width, height: ShowTime.size.height)
frame = CGRect(x: location.x - ShowTime.size / 2, y: location.y - ShowTime.size / 2, width: ShowTime.size, height: ShowTime.size)
if ShowTime.shouldShowForce {
let scale = 1 + (0.5 * touch.normalizedForce)
CATransaction.begin()
Expand Down Expand Up @@ -167,7 +167,7 @@ class TouchView: UILabel {
}

private func style(with touch: UITouch) {
layer.cornerRadius = ShowTime.size.height / 2
layer.cornerRadius = ShowTime.size / 2
layer.borderColor = ShowTime.strokeColor.cgColor
layer.borderWidth = ShowTime.strokeWidth
backgroundColor = ShowTime.fillColor == .auto ? ShowTime.strokeColor.withAlphaComponent(0.5) : ShowTime.fillColor
Expand All @@ -185,20 +185,33 @@ var _touches = [UITouch : TouchView]()

extension UIWindow {

struct Swizzled { static var once = false } // Workaround for missing dispatch_once in Swift 3

open override var layer: CALayer {
UIWindow.swizzle() // TODO: Only swizzle when enabled
if ShowTime.shouldEnable {
UIWindow.swizzle()
} else {
UIWindow.unswizzle()
}
return super.layer
}

private class func swizzle() { // `initialize()` removed in Swift 4
struct Swizzled { static var once = false } // Workaround for missing dispatch_once in Swift 3
guard !Swizzled.once else { return }
Swizzled.once = true
guard let original = class_getInstanceMethod(self, #selector(UIWindow.sendEvent(_:))) else { return }
guard let new = class_getInstanceMethod(self, #selector(UIWindow.swizzled_sendEvent(_:))) else { return }
method_exchangeImplementations(original, new)
}

private class func unswizzle() {
guard Swizzled.once else { return }
Swizzled.once = false
guard let original = class_getInstanceMethod(self, #selector(UIWindow.sendEvent(_:))) else { return }
guard let new = class_getInstanceMethod(self, #selector(UIWindow.swizzled_sendEvent(_:))) else { return }
method_exchangeImplementations(new, original)
}

@objc private func swizzled_sendEvent(_ event: UIEvent) {
swizzled_sendEvent(event)
guard ShowTime.shouldEnable else { return removeAllTouchViews() }
Expand Down