|
|
|
@@ -5,8 +5,6 @@
|
|
|
|
|
// Copyright © 2021 Duraid Abdul. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
//#if canImport(UIKit)
|
|
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
|
@@ -62,10 +60,11 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
|
|
|
|
|
lumaView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
|
|
lumaWidthAnchor = lumaView.widthAnchor.constraint(equalTo: consoleView.widthAnchor)
|
|
|
|
|
lumaHeightAnchor = lumaView.heightAnchor.constraint(equalToConstant: consoleView.frame.size.height)
|
|
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
|
lumaView.widthAnchor.constraint(equalTo: consoleView.widthAnchor),
|
|
|
|
|
lumaWidthAnchor,
|
|
|
|
|
lumaHeightAnchor,
|
|
|
|
|
lumaView.centerXAnchor.constraint(equalTo: consoleView.centerXAnchor),
|
|
|
|
|
lumaView.centerYAnchor.constraint(equalTo: consoleView.centerYAnchor)
|
|
|
|
@@ -74,6 +73,32 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
return lumaView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
lazy var hideButton: UIButton = {
|
|
|
|
|
let button = UIButton()
|
|
|
|
|
|
|
|
|
|
button.addAction(UIAction(handler: { [self] _ in
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1) {
|
|
|
|
|
consoleView.center = nearestTargetTo(consoleView.center, possibleTargets: possibleEndpoints.dropLast())
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
grabberMode = false
|
|
|
|
|
}), for: .touchUpInside)
|
|
|
|
|
|
|
|
|
|
consoleView.addSubview(button)
|
|
|
|
|
|
|
|
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
|
button.widthAnchor.constraint(equalTo: consoleView.widthAnchor),
|
|
|
|
|
button.heightAnchor.constraint(equalTo: consoleView.heightAnchor),
|
|
|
|
|
button.centerXAnchor.constraint(equalTo: consoleView.centerXAnchor),
|
|
|
|
|
button.centerYAnchor.constraint(equalTo: consoleView.centerYAnchor)
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
button.isHidden = true
|
|
|
|
|
|
|
|
|
|
return button
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
/// The fixed size of the console view.
|
|
|
|
|
lazy var consoleSize = defaultConsoleSize {
|
|
|
|
|
didSet {
|
|
|
|
@@ -157,10 +182,10 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
|
|
|
|
|
// Left edge hiding endpoints.
|
|
|
|
|
if consoleView.center.y < (UIScreen.portraitSize.height - (temporaryKeyboardHeightValueTracker ?? 0)) / 2 {
|
|
|
|
|
endpoints.append(CGPoint(x: -consoleSize.width / 2 + 10,
|
|
|
|
|
endpoints.append(CGPoint(x: -consoleSize.width / 2 + 28,
|
|
|
|
|
y: endpoints[0].y))
|
|
|
|
|
} else {
|
|
|
|
|
endpoints.append(CGPoint(x: -consoleSize.width / 2 + 10,
|
|
|
|
|
endpoints.append(CGPoint(x: -consoleSize.width / 2 + 28,
|
|
|
|
|
y: endpoints[1].y))
|
|
|
|
|
}
|
|
|
|
|
} else if consoleView.frame.maxX >= UIScreen.portraitSize.width {
|
|
|
|
@@ -170,10 +195,10 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
|
|
|
|
|
// Right edge hiding endpoints.
|
|
|
|
|
if consoleView.center.y < (UIScreen.portraitSize.height - (temporaryKeyboardHeightValueTracker ?? 0)) / 2 {
|
|
|
|
|
endpoints.append(CGPoint(x: UIScreen.portraitSize.width + consoleSize.width / 2 - 10,
|
|
|
|
|
endpoints.append(CGPoint(x: UIScreen.portraitSize.width + consoleSize.width / 2 - 28,
|
|
|
|
|
y: endpoints[0].y))
|
|
|
|
|
} else {
|
|
|
|
|
endpoints.append(CGPoint(x: UIScreen.portraitSize.width + consoleSize.width / 2 - 10,
|
|
|
|
|
endpoints.append(CGPoint(x: UIScreen.portraitSize.width + consoleSize.width / 2 - 28,
|
|
|
|
|
y: endpoints[1].y))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -224,7 +249,6 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
consoleView.layer.shadowRadius = 16
|
|
|
|
|
consoleView.layer.shadowOpacity = 0.5
|
|
|
|
|
consoleView.layer.shadowOffset = CGSize(width: 0, height: 2)
|
|
|
|
|
consoleView.center = possibleEndpoints.first!
|
|
|
|
|
consoleView.alpha = 0
|
|
|
|
|
|
|
|
|
|
consoleView.layer.cornerRadius = 22
|
|
|
|
@@ -301,6 +325,8 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
menuButton.showsMenuAsPrimaryAction = true
|
|
|
|
|
consoleView.addSubview(menuButton)
|
|
|
|
|
|
|
|
|
|
let _ = hideButton
|
|
|
|
|
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
|
|
|
|
|
}
|
|
|
|
@@ -309,6 +335,25 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
func configureWindow() {
|
|
|
|
|
var windowSceneFound = false
|
|
|
|
|
|
|
|
|
|
// Update console cached based on last-cached origin.
|
|
|
|
|
func updateConsoleOrigin() {
|
|
|
|
|
let cachedConsolePosition = CGPoint(x: UserDefaults.standard.object(forKey: "LocalConsole_X") as? CGFloat ?? possibleEndpoints.first!.x,
|
|
|
|
|
y: UserDefaults.standard.object(forKey: "LocalConsole_Y") as? CGFloat ?? possibleEndpoints.first!.y)
|
|
|
|
|
|
|
|
|
|
consoleView.center = cachedConsolePosition // Update console center so possibleEndpoints are calculated correctly.
|
|
|
|
|
consoleView.center = nearestTargetTo(cachedConsolePosition, possibleTargets: possibleEndpoints)
|
|
|
|
|
|
|
|
|
|
if consoleView.center.x < 0 || consoleView.center.x > UIScreen.portraitSize.width {
|
|
|
|
|
grabberMode = true
|
|
|
|
|
scrollLocked = !grabberMode
|
|
|
|
|
|
|
|
|
|
consoleView.layer.removeAllAnimations()
|
|
|
|
|
lumaView.layer.removeAllAnimations()
|
|
|
|
|
menuButton.layer.removeAllAnimations()
|
|
|
|
|
consoleTextView.layer.removeAllAnimations()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure console window.
|
|
|
|
|
func fetchWindowScene() {
|
|
|
|
|
let windowScene = UIApplication.shared
|
|
|
|
@@ -327,11 +372,11 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
consoleWindow?.addSubview(consoleView)
|
|
|
|
|
|
|
|
|
|
UIWindow.swizzleStatusBarAppearanceOverride
|
|
|
|
|
|
|
|
|
|
updateConsoleOrigin()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fetchWindowScene()
|
|
|
|
|
|
|
|
|
|
/// Ensures the window is configured (i.e. scene has been found). If not, delay and wait for a scene to prepare itself, then try again.
|
|
|
|
|
for i in 1...10 {
|
|
|
|
|
|
|
|
|
@@ -402,22 +447,21 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
|
|
|
|
|
if grabberMode {
|
|
|
|
|
|
|
|
|
|
if oldValue == false {
|
|
|
|
|
lumaView.layer.cornerRadius = consoleView.layer.cornerRadius
|
|
|
|
|
lumaHeightAnchor.constant = consoleView.frame.size.height
|
|
|
|
|
consoleView.layoutIfNeeded()
|
|
|
|
|
}
|
|
|
|
|
lumaView.layer.cornerRadius = consoleView.layer.cornerRadius
|
|
|
|
|
lumaHeightAnchor.constant = consoleView.frame.size.height
|
|
|
|
|
consoleView.layoutIfNeeded()
|
|
|
|
|
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1) { [self] in
|
|
|
|
|
consoleTextView.alpha = 0
|
|
|
|
|
menuButton.alpha = 0
|
|
|
|
|
borderView.alpha = 0
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1) { [self] in
|
|
|
|
|
lumaView.foregroundView.alpha = 0
|
|
|
|
|
borderView.alpha = 0
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
|
|
|
|
|
lumaWidthAnchor.constant = -34
|
|
|
|
|
lumaHeightAnchor.constant = 96
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.4, dampingRatio: 1) { [self] in
|
|
|
|
|
lumaView.layer.cornerRadius = 8
|
|
|
|
@@ -425,9 +469,12 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
}.startAnimation(afterDelay: 0.06)
|
|
|
|
|
|
|
|
|
|
consoleTextView.isUserInteractionEnabled = false
|
|
|
|
|
hideButton.isHidden = false
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
lumaHeightAnchor.constant = consoleView.frame.size.height
|
|
|
|
|
lumaWidthAnchor.constant = 0
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.4, dampingRatio: 1) { [self] in
|
|
|
|
|
consoleView.layoutIfNeeded()
|
|
|
|
|
lumaView.layer.cornerRadius = consoleView.layer.cornerRadius
|
|
|
|
@@ -444,6 +491,7 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
|
|
|
|
|
consoleTextView.isUserInteractionEnabled = true
|
|
|
|
|
hideButton.isHidden = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -606,10 +654,6 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc func toggleLock() {
|
|
|
|
|
scrollLocked.toggle()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func commitTextChanges(requestMenuUpdate menuUpdateRequested: Bool) {
|
|
|
|
|
|
|
|
|
|
if consoleTextView.contentOffset.y > consoleTextView.contentSize.height - consoleTextView.bounds.size.height - 20 {
|
|
|
|
@@ -758,10 +802,10 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
case .cancelled, .ended:
|
|
|
|
|
|
|
|
|
|
scrollLocked = true
|
|
|
|
|
if !grabberMode { scrollLocked = true }
|
|
|
|
|
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.8, dampingRatio: 0.5) { [self] in
|
|
|
|
|
consoleView.transform = .init(scaleX: 1, y: 1)
|
|
|
|
|
consoleView.transform = .identity
|
|
|
|
|
}.startAnimation()
|
|
|
|
|
|
|
|
|
|
UIViewPropertyAnimator(duration: 0.4, dampingRatio: 1) { [self] in
|
|
|
|
@@ -792,13 +836,9 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
consoleView.center.y = initialViewLocation.y + translation.y
|
|
|
|
|
|
|
|
|
|
if consoleView.frame.maxX > 30 && consoleView.frame.minX < UIScreen.portraitSize.width - 30 {
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
|
|
|
|
self.grabberMode = false
|
|
|
|
|
}
|
|
|
|
|
self.grabberMode = false
|
|
|
|
|
} else {
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
|
|
|
|
self.grabberMode = true
|
|
|
|
|
}
|
|
|
|
|
self.grabberMode = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case .ended, .cancelled:
|
|
|
|
@@ -818,13 +858,16 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
dy: relativeVelocity(forVelocity: velocity.y, from: consoleView.center.y, to: nearestTargetPosition.y)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
let timingParameters = UISpringTimingParameters(damping: 1, response: 0.4, initialVelocity: relativeInitialVelocity)
|
|
|
|
|
let timingParameters = UISpringTimingParameters(damping: 0.85, response: 0.45, initialVelocity: relativeInitialVelocity)
|
|
|
|
|
let positionAnimator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters)
|
|
|
|
|
positionAnimator.addAnimations { [self] in
|
|
|
|
|
consoleView.center = nearestTargetPosition
|
|
|
|
|
}
|
|
|
|
|
positionAnimator.startAnimation()
|
|
|
|
|
|
|
|
|
|
UserDefaults.standard.set(nearestTargetPosition.x, forKey: "LocalConsole_X")
|
|
|
|
|
UserDefaults.standard.set(nearestTargetPosition.y, forKey: "LocalConsole_Y")
|
|
|
|
|
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
|
|
|
|
self.grabberMode = nearestTargetPosition.x < 0 || nearestTargetPosition.x > UIScreen.portraitSize.width
|
|
|
|
|
self.scrollLocked = !self.grabberMode
|
|
|
|
@@ -866,15 +909,9 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
|
|
|
|
|
switch recognizer.state {
|
|
|
|
|
case .began:
|
|
|
|
|
consolePiPTouchDown()
|
|
|
|
|
case .cancelled:
|
|
|
|
|
consolePiPTouchUp()
|
|
|
|
|
case .changed:
|
|
|
|
|
break
|
|
|
|
|
case .ended:
|
|
|
|
|
consolePiPTouchUp()
|
|
|
|
|
case .failed:
|
|
|
|
|
consolePiPTouchUp()
|
|
|
|
|
case .possible:
|
|
|
|
|
case .ended, .cancelled, .possible, .failed:
|
|
|
|
|
consolePiPTouchUp()
|
|
|
|
|
@unknown default:
|
|
|
|
|
break
|
|
|
|
@@ -942,8 +979,6 @@ extension UIWindow {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
class LumaView: UIView {
|
|
|
|
|
lazy var visualEffectView: UIView = {
|
|
|
|
|
Bundle(path: "/Sys" + "tem/Lib" + "rary/Private" + "Frameworks/Material" + "Kit." + "framework")!.load()
|
|
|
|
@@ -1007,6 +1042,9 @@ class LumaView: UIView {
|
|
|
|
|
let _ = visualEffectView
|
|
|
|
|
let _ = foregroundView
|
|
|
|
|
|
|
|
|
|
visualEffectView.isUserInteractionEnabled = false
|
|
|
|
|
foregroundView.isUserInteractionEnabled = false
|
|
|
|
|
|
|
|
|
|
layer.cornerCurve = .continuous
|
|
|
|
|
clipsToBounds = true
|
|
|
|
|
}
|
|
|
|
|