Merge pull request #736 from cdoncarroll/cdoncarroll-VisibleWindowTouches
Add Debug Option For Displaying Touches
This commit is contained in:
commit
da3f631380
|
@ -23,4 +23,12 @@ extension UIApplication {
|
||||||
return version == build ? "v\(version)" : "v\(version) (\(build))"
|
return version == build ? "v\(version)" : "v\(version) (\(build))"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getKeyWindow() -> UIWindow? {
|
||||||
|
return UIApplication
|
||||||
|
.shared
|
||||||
|
.connectedScenes
|
||||||
|
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
|
||||||
|
.first { $0.isKeyWindow }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,10 @@ extension HomeTimelineViewController {
|
||||||
identifier: nil,
|
identifier: nil,
|
||||||
options: [],
|
options: [],
|
||||||
children: [
|
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
|
UIAction(title: "Toggle EmptyView", image: UIImage(systemName: "clear"), attributes: []) { [weak self] action in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if self.emptyView.superview != nil {
|
if self.emptyView.superview != nil {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Combine
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
import MastodonCore
|
import MastodonCore
|
||||||
import MastodonExtension
|
import MastodonExtension
|
||||||
|
import MastodonUI
|
||||||
|
|
||||||
#if PROFILE
|
#if PROFILE
|
||||||
import FPSIndicator
|
import FPSIndicator
|
||||||
|
@ -35,8 +36,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
guard let windowScene = scene as? UIWindowScene else { return }
|
guard let windowScene = scene as? UIWindowScene else { return }
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
let window = TouchesVisibleWindow(windowScene: windowScene)
|
||||||
|
self.window = window
|
||||||
|
#else
|
||||||
let window = UIWindow(windowScene: windowScene)
|
let window = UIWindow(windowScene: windowScene)
|
||||||
self.window = window
|
self.window = window
|
||||||
|
#endif
|
||||||
|
|
||||||
// set tint color
|
// set tint color
|
||||||
window.tintColor = UIColor.label
|
window.tintColor = UIColor.label
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue