Merge pull request #736 from cdoncarroll/cdoncarroll-VisibleWindowTouches

Add Debug Option For Displaying Touches
This commit is contained in:
Nathan Mattes 2022-12-19 15:51:26 +01:00 committed by GitHub
commit da3f631380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 0 deletions

View File

@ -22,5 +22,13 @@ extension UIApplication {
return version == build ? "v\(version)" : "v\(version) (\(build))"
}
func getKeyWindow() -> UIWindow? {
return UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
}
}

View File

@ -122,6 +122,10 @@ extension HomeTimelineViewController {
identifier: nil,
options: [],
children: [
UIAction(title: "Toggle Visible Touches", image: UIImage(systemName: "hand.tap"), attributes: []) { _ in
guard let window = UIApplication.shared.getKeyWindow() as? TouchesVisibleWindow else { return }
window.touchesVisible = !window.touchesVisible
},
UIAction(title: "Toggle EmptyView", image: UIImage(systemName: "clear"), attributes: []) { [weak self] action in
guard let self = self else { return }
if self.emptyView.superview != nil {

View File

@ -11,6 +11,7 @@ import Combine
import CoreDataStack
import MastodonCore
import MastodonExtension
import MastodonUI
#if PROFILE
import FPSIndicator
@ -35,8 +36,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
#if DEBUG
let window = TouchesVisibleWindow(windowScene: windowScene)
self.window = window
#else
let window = UIWindow(windowScene: windowScene)
self.window = window
#endif
// set tint color
window.tintColor = UIColor.label

View File

@ -0,0 +1,135 @@
//
// TouchesVisibleWindow.swift
//
//
// Created by Chase Carroll on 12/5/22.
//
#if DEBUG
import UIKit
/// View that represents a single touch from the user.
private final class TouchView: UIView {
private let blurView = UIVisualEffectView(effect: nil)
override var frame: CGRect {
didSet {
layer.cornerRadius = frame.height / 2.0
}
}
override init(frame: CGRect) {
super.init(frame: frame)
let isLightMode = traitCollection.userInterfaceStyle == .light
backgroundColor = .clear
layer.masksToBounds = true
layer.cornerCurve = .circular
layer.borderColor = isLightMode ? UIColor.gray.cgColor : UIColor.white.cgColor
layer.borderWidth = 2.0
let blurEffect = isLightMode ?
UIBlurEffect(style: .systemUltraThinMaterialDark) :
UIBlurEffect(style: .systemUltraThinMaterialLight)
blurView.effect = blurEffect
addSubview(blurView)
}
@available(iOS, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
blurView.frame = bounds
}
}
/// `UIWindow` subclass that renders visual representations of the user's touches.
public final class TouchesVisibleWindow: UIWindow {
public var touchesVisible = false {
didSet {
if !touchesVisible {
cleanUpAllTouches()
}
}
}
private var touchViews: [UITouch : TouchView] = [:]
private func newTouchView() -> TouchView {
let touchSize = 44.0
return TouchView(frame: CGRect(
origin: .zero,
size: CGSize(
width: touchSize,
height: touchSize
)
))
}
private func cleanupTouch(_ touch: UITouch) {
guard let touchView = touchViews[touch] else {
return
}
touchView.removeFromSuperview()
touchViews.removeValue(forKey: touch)
}
private func cleanUpAllTouches() {
for (_, touchView) in touchViews {
touchView.removeFromSuperview()
}
touchViews.removeAll()
}
public override func sendEvent(_ event: UIEvent) {
if touchesVisible {
let touches = event.allTouches
guard
let touches = touches,
touches.count > 0
else {
cleanUpAllTouches()
super.sendEvent(event)
return
}
for touch in touches {
let touchLocation = touch.location(in: self)
switch touch.phase {
case .began:
let touchView = newTouchView()
touchView.center = touchLocation
addSubview(touchView)
touchViews[touch] = touchView
case .moved:
if let touchView = touchViews[touch] {
touchView.center = touchLocation
}
case .ended, .cancelled:
cleanupTouch(touch)
default:
break
}
}
}
super.sendEvent(event)
}
}
#endif