[WIP] Stories

This commit is contained in:
Ali 2023-06-17 00:26:18 +03:00
parent b64aa1445c
commit 8e5241f064
3 changed files with 69 additions and 35 deletions

View File

@ -422,7 +422,7 @@ public struct Transition {
delay: 0.0, delay: 0.0,
curve: curve, curve: curve,
removeOnCompletion: true, removeOnCompletion: true,
additive: true, additive: false,
completion: completion completion: completion
) )
} }
@ -497,21 +497,35 @@ public struct Transition {
} }
public func setTransform(layer: CALayer, transform: CATransform3D, completion: ((Bool) -> Void)? = nil) { public func setTransform(layer: CALayer, transform: CATransform3D, completion: ((Bool) -> Void)? = nil) {
let t = layer.presentation()?.transform ?? layer.transform
if CATransform3DEqualToTransform(t, transform) {
if let animation = layer.animation(forKey: "transform") as? CABasicAnimation, let toValue = animation.toValue as? NSValue { if let animation = layer.animation(forKey: "transform") as? CABasicAnimation, let toValue = animation.toValue as? NSValue {
if CATransform3DEqualToTransform(toValue.caTransform3DValue, transform) { if CATransform3DEqualToTransform(toValue.caTransform3DValue, transform) {
completion?(true) completion?(true)
return return
} }
} else { } else if let animation = layer.animation(forKey: "transform") as? CAKeyframeAnimation, let toValue = animation.values?.last as? NSValue {
if CATransform3DEqualToTransform(toValue.caTransform3DValue, transform) {
completion?(true) completion?(true)
return return
} }
} }
if CATransform3DEqualToTransform(layer.transform, transform) {
completion?(true)
return
}
switch self.animation { switch self.animation {
case .none: case .none:
if layer.animation(forKey: "transform") != nil {
if let animation = layer.animation(forKey: "transform") as? CAKeyframeAnimation, let toValue = animation.values?.last as? NSValue {
if CATransform3DEqualToTransform(toValue.caTransform3DValue, transform) {
completion?(true)
return
}
}
layer.removeAnimation(forKey: "transform")
}
layer.transform = transform layer.transform = transform
completion?(true) completion?(true)
case let .curve(duration, curve): case let .curve(duration, curve):
@ -540,14 +554,19 @@ public struct Transition {
public func setTransformAsKeyframes(layer: CALayer, transform: (CGFloat, Bool) -> CATransform3D, completion: ((Bool) -> Void)? = nil) { public func setTransformAsKeyframes(layer: CALayer, transform: (CGFloat, Bool) -> CATransform3D, completion: ((Bool) -> Void)? = nil) {
let finalTransform = transform(1.0, true) let finalTransform = transform(1.0, true)
let t = layer.presentation()?.transform ?? layer.transform let t = layer.transform
if CATransform3DEqualToTransform(t, finalTransform) { do {
if let animation = layer.animation(forKey: "transform") as? CABasicAnimation, let toValue = animation.toValue as? NSValue { if let animation = layer.animation(forKey: "transform") as? CABasicAnimation, let toValue = animation.toValue as? NSValue {
if CATransform3DEqualToTransform(toValue.caTransform3DValue, finalTransform) { if CATransform3DEqualToTransform(toValue.caTransform3DValue, finalTransform) {
completion?(true) completion?(true)
return return
} }
} else { } else if let animation = layer.animation(forKey: "transform") as? CAKeyframeAnimation, let toValue = animation.values?.last as? NSValue {
if CATransform3DEqualToTransform(toValue.caTransform3DValue, finalTransform) {
completion?(true)
return
}
} else if CATransform3DEqualToTransform(t, finalTransform) {
completion?(true) completion?(true)
return return
} }
@ -555,6 +574,9 @@ public struct Transition {
switch self.animation { switch self.animation {
case .none: case .none:
if layer.animation(forKey: "transform") != nil {
layer.removeAnimation(forKey: "transform")
}
layer.transform = transform(1.0, true) layer.transform = transform(1.0, true)
completion?(true) completion?(true)
case let .curve(duration, curve): case let .curve(duration, curve):

View File

@ -185,7 +185,7 @@ final class PendingStoryManager {
if let currentPendingItemContext = self.currentPendingItemContext, currentPendingItemContext.item.stableId == stableId { if let currentPendingItemContext = self.currentPendingItemContext, currentPendingItemContext.item.stableId == stableId {
next(currentPendingItemContext.progress) next(currentPendingItemContext.progress)
} else { } else {
next(1.0) next(0.0)
} }
let queue = self.queue let queue = self.queue

View File

@ -250,18 +250,30 @@ private final class StoryContainerScreenComponent: Component {
return true return true
} }
private func beginHorizontalPan() { private func beginHorizontalPan(translation: CGPoint) {
if self.layer.animation(forKey: "panState") != nil {
self.layer.removeAnimation(forKey: "panState") self.layer.removeAnimation(forKey: "panState")
}
let updateImmediately = abs(translation.x) > 0.0
if let itemSetPanState = self.itemSetPanState, !itemSetPanState.didBegin { if let itemSetPanState = self.itemSetPanState, !itemSetPanState.didBegin {
self.itemSetPanState = ItemSetPanState(fraction: 0.0, didBegin: true) self.itemSetPanState = ItemSetPanState(fraction: 0.0, didBegin: true)
if !updateImmediately {
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut))) self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
}
} else { } else {
self.itemSetPanState = ItemSetPanState(fraction: 0.0, didBegin: true) self.itemSetPanState = ItemSetPanState(fraction: 0.0, didBegin: true)
if !updateImmediately {
self.state?.updated(transition: .immediate) self.state?.updated(transition: .immediate)
} }
} }
if updateImmediately {
self.updateHorizontalPan(translation: translation)
}
}
private func updateHorizontalPan(translation: CGPoint) { private func updateHorizontalPan(translation: CGPoint) {
var translation = translation var translation = translation
@ -341,7 +353,7 @@ private final class StoryContainerScreenComponent: Component {
@objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) {
switch recognizer.state { switch recognizer.state {
case .began: case .began:
self.beginHorizontalPan() self.beginHorizontalPan(translation: recognizer.translation(in: self))
case .changed: case .changed:
self.updateHorizontalPan(translation: recognizer.translation(in: self)) self.updateHorizontalPan(translation: recognizer.translation(in: self))
case .cancelled, .ended: case .cancelled, .ended:
@ -409,14 +421,14 @@ private final class StoryContainerScreenComponent: Component {
if stateValue.previousSlice == nil { if stateValue.previousSlice == nil {
} else { } else {
self.beginHorizontalPan() self.beginHorizontalPan(translation: CGPoint())
self.commitHorizontalPan(velocity: CGPoint(x: 100.0, y: 0.0)) self.commitHorizontalPan(velocity: CGPoint(x: 100.0, y: 0.0))
} }
} else if location.x > currentItemView.frame.maxX { } else if location.x > currentItemView.frame.maxX {
if stateValue.nextSlice == nil { if stateValue.nextSlice == nil {
environment.controller()?.dismiss() environment.controller()?.dismiss()
} else { } else {
self.beginHorizontalPan() self.beginHorizontalPan(translation: CGPoint())
self.commitHorizontalPan(velocity: CGPoint(x: -100.0, y: 0.0)) self.commitHorizontalPan(velocity: CGPoint(x: -100.0, y: 0.0))
} }
} }
@ -430,11 +442,9 @@ private final class StoryContainerScreenComponent: Component {
} }
if subview is ItemSetView { if subview is ItemSetView {
if self.itemSetPanState == nil {
if let result = subview.hitTest(self.convert(point, to: subview), with: event) { if let result = subview.hitTest(self.convert(point, to: subview), with: event) {
return result return result
} }
}
} else { } else {
if let result = subview.hitTest(self.convert(self.convert(point, to: subview), to: subview), with: event) { if let result = subview.hitTest(self.convert(self.convert(point, to: subview), to: subview), with: event) {
return result return result
@ -738,7 +748,7 @@ private final class StoryContainerScreenComponent: Component {
if stateValue.nextSlice == nil { if stateValue.nextSlice == nil {
environment.controller()?.dismiss() environment.controller()?.dismiss()
} else { } else {
self.beginHorizontalPan() self.beginHorizontalPan(translation: CGPoint())
self.updateHorizontalPan(translation: CGPoint()) self.updateHorizontalPan(translation: CGPoint())
self.commitHorizontalPan(velocity: CGPoint(x: -100.0, y: 0.0)) self.commitHorizontalPan(velocity: CGPoint(x: -100.0, y: 0.0))
} }
@ -750,7 +760,7 @@ private final class StoryContainerScreenComponent: Component {
} }
} }
} else { } else {
self.beginHorizontalPan() self.beginHorizontalPan(translation: CGPoint())
self.updateHorizontalPan(translation: CGPoint()) self.updateHorizontalPan(translation: CGPoint())
self.commitHorizontalPan(velocity: CGPoint(x: 100.0, y: 0.0)) self.commitHorizontalPan(velocity: CGPoint(x: 100.0, y: 0.0))
} }
@ -882,27 +892,29 @@ private final class StoryContainerScreenComponent: Component {
Transition.immediate.setTransform(view: itemSetComponentView, transform: faceTransform) Transition.immediate.setTransform(view: itemSetComponentView, transform: faceTransform)
Transition.immediate.setTransform(layer: itemSetView.tintLayer, transform: faceTransform) Transition.immediate.setTransform(layer: itemSetView.tintLayer, transform: faceTransform)
if let previousRotationFraction = itemSetView.rotationFraction { if let previousRotationFraction = itemSetView.rotationFraction, !itemSetTransition.animation.isImmediate {
let fromT = previousRotationFraction let fromT = previousRotationFraction
let toT = panFraction let toT = panFraction + cubeAdditionalRotationFraction
itemSetTransition.setTransformAsKeyframes(view: itemSetView, transform: { sourceT, isFinal in itemSetTransition.setTransformAsKeyframes(view: itemSetView, transform: { sourceT, isFinal in
let t = fromT * (1.0 - sourceT) + toT * sourceT let t = fromT * (1.0 - sourceT) + toT * sourceT
if abs((t + cubeAdditionalRotationFraction) - 0.0) < 0.0001 {
if isFinal { if isFinal {
if abs(t - 0.0) <= 0.0001 {
return CATransform3DIdentity return CATransform3DIdentity
} }
} }
return calculateCubeTransform(rotationFraction: t + cubeAdditionalRotationFraction, sideAngle: sideAngle, cubeSize: itemFrame.size) return calculateCubeTransform(rotationFraction: t, sideAngle: sideAngle, cubeSize: itemFrame.size)
}) })
} else { } else {
if panFraction == 0.0 { let updatedTransform: CATransform3D
itemSetTransition.setTransform(view: itemSetView, transform: CATransform3DIdentity) if abs(panFraction + cubeAdditionalRotationFraction) <= 0.0001 {
updatedTransform = CATransform3DIdentity
} else { } else {
itemSetTransition.setTransform(view: itemSetView, transform: calculateCubeTransform(rotationFraction: panFraction + cubeAdditionalRotationFraction, sideAngle: sideAngle, cubeSize: itemFrame.size)) updatedTransform = calculateCubeTransform(rotationFraction: panFraction + cubeAdditionalRotationFraction, sideAngle: sideAngle, cubeSize: itemFrame.size)
} }
itemSetTransition.setTransform(view: itemSetView, transform: updatedTransform)
} }
itemSetView.rotationFraction = panFraction itemSetView.rotationFraction = panFraction + cubeAdditionalRotationFraction
var alphaFraction = panFraction + cubeAdditionalRotationFraction var alphaFraction = panFraction + cubeAdditionalRotationFraction