mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Ongoing work on the updated entity input
This commit is contained in:
@@ -128,6 +128,16 @@ private extension Transition.Animation.Curve {
|
||||
}
|
||||
}
|
||||
|
||||
public extension Transition.Animation {
|
||||
var isImmediate: Bool {
|
||||
if case .none = self {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Transition {
|
||||
public enum Animation {
|
||||
public enum Curve {
|
||||
@@ -245,6 +255,61 @@ public struct Transition {
|
||||
}
|
||||
}
|
||||
|
||||
public func setBounds(layer: CALayer, bounds: CGRect, completion: ((Bool) -> Void)? = nil) {
|
||||
if layer.bounds == bounds {
|
||||
completion?(true)
|
||||
return
|
||||
}
|
||||
switch self.animation {
|
||||
case .none:
|
||||
layer.bounds = bounds
|
||||
layer.removeAnimation(forKey: "bounds")
|
||||
completion?(true)
|
||||
case .curve:
|
||||
let previousBounds = layer.presentation()?.bounds ?? layer.bounds
|
||||
layer.bounds = bounds
|
||||
|
||||
self.animateBounds(layer: layer, from: previousBounds, to: layer.bounds, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
public func setPosition(layer: CALayer, position: CGPoint, completion: ((Bool) -> Void)? = nil) {
|
||||
if layer.position == position {
|
||||
completion?(true)
|
||||
return
|
||||
}
|
||||
switch self.animation {
|
||||
case .none:
|
||||
layer.position = position
|
||||
layer.removeAnimation(forKey: "position")
|
||||
completion?(true)
|
||||
case .curve:
|
||||
let previousPosition = layer.presentation()?.position ?? layer.position
|
||||
layer.position = position
|
||||
|
||||
self.animatePosition(layer: layer, from: previousPosition, to: layer.position, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
public func attachAnimation(view: UIView, completion: @escaping (Bool) -> Void) {
|
||||
switch self.animation {
|
||||
case .none:
|
||||
completion(true)
|
||||
case let .curve(duration, curve):
|
||||
view.layer.animate(
|
||||
from: 0.0 as NSNumber,
|
||||
to: 1.0 as NSNumber,
|
||||
keyPath: "attached\(UInt32.random(in: 0 ... UInt32.max))",
|
||||
duration: duration,
|
||||
delay: 0.0,
|
||||
curve: curve,
|
||||
removeOnCompletion: true,
|
||||
additive: true,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func setAlpha(view: UIView, alpha: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||
if view.alpha == alpha {
|
||||
completion?(true)
|
||||
@@ -356,11 +421,19 @@ public struct Transition {
|
||||
}
|
||||
|
||||
public func animatePosition(view: UIView, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
self.animatePosition(layer: view.layer, from: fromValue, to: toValue, additive: additive, completion: completion)
|
||||
}
|
||||
|
||||
public func animateBounds(view: UIView, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
self.animateBounds(layer: view.layer, from: fromValue, to: toValue, additive: additive, completion: completion)
|
||||
}
|
||||
|
||||
public func animatePosition(layer: CALayer, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
switch self.animation {
|
||||
case .none:
|
||||
completion?(true)
|
||||
case let .curve(duration, curve):
|
||||
view.layer.animate(
|
||||
layer.animate(
|
||||
from: NSValue(cgPoint: fromValue),
|
||||
to: NSValue(cgPoint: toValue),
|
||||
keyPath: "position",
|
||||
@@ -374,12 +447,12 @@ public struct Transition {
|
||||
}
|
||||
}
|
||||
|
||||
public func animateBounds(view: UIView, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
public func animateBounds(layer: CALayer, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
switch self.animation {
|
||||
case .none:
|
||||
break
|
||||
case let .curve(duration, curve):
|
||||
view.layer.animate(
|
||||
layer.animate(
|
||||
from: NSValue(cgRect: fromValue),
|
||||
to: NSValue(cgRect: toValue),
|
||||
keyPath: "bounds",
|
||||
|
||||
@@ -7,6 +7,7 @@ public final class Button: Component {
|
||||
public let tag: AnyObject?
|
||||
public let automaticHighlight: Bool
|
||||
public let action: () -> Void
|
||||
public let holdAction: (() -> Void)?
|
||||
|
||||
convenience public init(
|
||||
content: AnyComponent<Empty>,
|
||||
@@ -17,7 +18,8 @@ public final class Button: Component {
|
||||
minSize: nil,
|
||||
tag: nil,
|
||||
automaticHighlight: true,
|
||||
action: action
|
||||
action: action,
|
||||
holdAction: nil
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,13 +28,15 @@ public final class Button: Component {
|
||||
minSize: CGSize? = nil,
|
||||
tag: AnyObject? = nil,
|
||||
automaticHighlight: Bool = true,
|
||||
action: @escaping () -> Void
|
||||
action: @escaping () -> Void,
|
||||
holdAction: (() -> Void)?
|
||||
) {
|
||||
self.content = content
|
||||
self.minSize = minSize
|
||||
self.tag = tag
|
||||
self.automaticHighlight = automaticHighlight
|
||||
self.action = action
|
||||
self.holdAction = holdAction
|
||||
}
|
||||
|
||||
public func minSize(_ minSize: CGSize?) -> Button {
|
||||
@@ -41,7 +45,19 @@ public final class Button: Component {
|
||||
minSize: minSize,
|
||||
tag: self.tag,
|
||||
automaticHighlight: self.automaticHighlight,
|
||||
action: self.action
|
||||
action: self.action,
|
||||
holdAction: self.holdAction
|
||||
)
|
||||
}
|
||||
|
||||
public func withHoldAction(_ holdAction: (() -> Void)?) -> Button {
|
||||
return Button(
|
||||
content: self.content,
|
||||
minSize: self.minSize,
|
||||
tag: self.tag,
|
||||
automaticHighlight: self.automaticHighlight,
|
||||
action: self.action,
|
||||
holdAction: holdAction
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +67,8 @@ public final class Button: Component {
|
||||
minSize: self.minSize,
|
||||
tag: tag,
|
||||
automaticHighlight: self.automaticHighlight,
|
||||
action: self.action
|
||||
action: self.action,
|
||||
holdAction: self.holdAction
|
||||
)
|
||||
}
|
||||
|
||||
@@ -86,6 +103,9 @@ public final class Button: Component {
|
||||
}
|
||||
}
|
||||
|
||||
private var holdActionTriggerred: Bool = false
|
||||
private var holdActionTimer: Timer?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.contentView = ComponentHostView<Empty>()
|
||||
self.contentView.isUserInteractionEnabled = false
|
||||
@@ -101,6 +121,10 @@ public final class Button: Component {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.holdActionTimer?.invalidate()
|
||||
}
|
||||
|
||||
public func matches(tag: Any) -> Bool {
|
||||
if let component = self.component, let componentTag = component.tag {
|
||||
let tag = tag as AnyObject
|
||||
@@ -112,24 +136,69 @@ public final class Button: Component {
|
||||
}
|
||||
|
||||
@objc private func pressed() {
|
||||
self.component?.action()
|
||||
if self.holdActionTriggerred {
|
||||
self.holdActionTriggerred = false
|
||||
} else {
|
||||
self.component?.action()
|
||||
}
|
||||
}
|
||||
|
||||
override public func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
|
||||
self.currentIsHighlighted = true
|
||||
|
||||
self.holdActionTriggerred = false
|
||||
|
||||
if self.component?.holdAction != nil {
|
||||
self.holdActionTriggerred = true
|
||||
self.component?.action()
|
||||
|
||||
self.holdActionTimer?.invalidate()
|
||||
if #available(iOS 10.0, *) {
|
||||
let holdActionTimer = Timer(timeInterval: 1.0, repeats: false, block: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.holdActionTimer?.invalidate()
|
||||
strongSelf.component?.holdAction?()
|
||||
strongSelf.beginExecuteHoldActionTimer()
|
||||
})
|
||||
self.holdActionTimer = holdActionTimer
|
||||
RunLoop.main.add(holdActionTimer, forMode: .common)
|
||||
}
|
||||
}
|
||||
|
||||
return super.beginTracking(touch, with: event)
|
||||
}
|
||||
|
||||
private func beginExecuteHoldActionTimer() {
|
||||
self.holdActionTimer?.invalidate()
|
||||
if #available(iOS 10.0, *) {
|
||||
let holdActionTimer = Timer(timeInterval: 0.2, repeats: true, block: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.component?.holdAction?()
|
||||
})
|
||||
self.holdActionTimer = holdActionTimer
|
||||
RunLoop.main.add(holdActionTimer, forMode: .common)
|
||||
}
|
||||
}
|
||||
|
||||
override public func endTracking(_ touch: UITouch?, with event: UIEvent?) {
|
||||
self.currentIsHighlighted = false
|
||||
|
||||
self.holdActionTimer?.invalidate()
|
||||
self.holdActionTimer = nil
|
||||
|
||||
super.endTracking(touch, with: event)
|
||||
}
|
||||
|
||||
override public func cancelTracking(with event: UIEvent?) {
|
||||
self.currentIsHighlighted = false
|
||||
|
||||
self.holdActionTimer?.invalidate()
|
||||
self.holdActionTimer = nil
|
||||
|
||||
super.cancelTracking(with: event)
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +106,21 @@ public final class ComponentHostView<EnvironmentType>: UIView {
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if self.alpha.isZero {
|
||||
return nil
|
||||
}
|
||||
for view in self.subviews.reversed() {
|
||||
if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
let result = super.hitTest(point, with: event)
|
||||
return result
|
||||
if result != self {
|
||||
return result
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func findTaggedView(tag: Any) -> UIView? {
|
||||
|
||||
Reference in New Issue
Block a user