AnimatableView async setSource

commit_hash:052d29b05edfe0754ab9799f7040a7e6e341760d
This commit is contained in:
dmt021
2024-12-05 21:47:26 +03:00
parent 6b81dc2871
commit efbaeec203
7 changed files with 57 additions and 27 deletions
@@ -3,16 +3,41 @@ import Foundation
import LayoutKit
import VGSL
public protocol AnimatableViewFactory: AnyObject {
public protocol AsyncSourceAnimatableViewFactory: AnyObject {
func createAsyncSourceAnimatableView(withMode mode: AnimationRepeatMode, repeatCount count: Float)
-> AsyncSourceAnimatableView
}
/// This protocol is deprecated. Use AsyncSourceAnimatableViewFactory instead.
public protocol AnimatableViewFactory: AnyObject, AsyncSourceAnimatableViewFactory {
func createAnimatableView(withMode mode: AnimationRepeatMode, repeatCount count: Float)
-> AnimatableView
}
public protocol AnimatableView: ViewType {
extension AnimatableViewFactory {
public func createAsyncSourceAnimatableView(withMode mode: AnimationRepeatMode, repeatCount count: Float)
-> AsyncSourceAnimatableView {
createAnimatableView(withMode: mode, repeatCount: count)
}
}
public protocol AsyncSourceAnimatableView: ViewType {
func play()
func setSourceAsync(_ source: AnimationSourceType) async
}
/// This protocol is deprecated. Use AsyncSourceAnimatableView instead.
public protocol AnimatableView: AsyncSourceAnimatableView {
func setSource(_ source: AnimationSourceType)
}
extension AnimatableView {
public func setSourceAsync(_ source: AnimationSourceType) async {
setSource(source)
}
}
@frozen
public enum AnimationRepeatMode {
case restart
@@ -4,7 +4,7 @@ import LayoutKit
import VGSL
final class AnimationBlockView: BlockView {
var animatableView: AnimatableView? {
var animatableView: AsyncSourceAnimatableView? {
didSet {
if let animatablView = animatableView {
oldValue?.removeFrom(self)
@@ -29,13 +29,16 @@ final class AnimationBlockView: BlockView {
.requestAnimationWithCompletion { [weak self] animationSource in
guard let self,
newValue === self.animationHolder,
let animationSource else {
let animationSource,
let view = self.animatableView else {
return
}
self.animatableView?.contentMode = animationContentMode
self.animatableView?.setSource(animationSource)
self.animatableView?.play()
view.contentMode = animationContentMode
Task { @MainActor in
await view.setSourceAsync(animationSource)
view.play()
}
}
}
}
@@ -6,7 +6,7 @@ import LayoutKit
import VGSL
final class LottieAnimationBlock: SizeForwardingBlock {
let animatableView: Lazy<AnimatableView>
let animatableView: Lazy<AsyncSourceAnimatableView>
let animationHolder: AnimationHolder
let sizeProvider: Block
let scale: DivImageScale
@@ -16,7 +16,7 @@ final class LottieAnimationBlock: SizeForwardingBlock {
}
init(
animatableView: Lazy<AnimatableView>,
animatableView: Lazy<AsyncSourceAnimatableView>,
animationHolder: AnimationHolder,
sizeProvider: Block,
scale: DivImageScale
@@ -7,12 +7,12 @@ import VGSL
public final class LottieExtensionHandler: DivExtensionHandler {
public let id = "lottie"
private let factory: AnimatableViewFactory
private let factory: AsyncSourceAnimatableViewFactory
private let requester: URLResourceRequesting
private let localAnimationDataProvider: ((URL) -> Data?)?
public init(
factory: AnimatableViewFactory,
factory: AsyncSourceAnimatableViewFactory,
requester: URLResourceRequesting,
localAnimationDataProvider: ((URL) -> Data?)? = nil
) {
@@ -49,7 +49,7 @@ public final class LottieExtensionHandler: DivExtensionHandler {
return LottieAnimationBlock(
animatableView: Lazy(
getter: {
self.factory.createAnimatableView(
self.factory.createAsyncSourceAnimatableView(
withMode: params.repeatMode,
repeatCount: params.repeatCount
)
@@ -5,7 +5,7 @@ import VGSL
public final class RiveAnimationBlock: BlockWithTraits {
let animationHolder: AnimationHolder
let animatableView: Lazy<AnimatableView>
let animatableView: Lazy<AsyncSourceAnimatableView>
public let widthTrait: LayoutTrait
public let heightTrait: LayoutTrait
@@ -15,7 +15,7 @@ public final class RiveAnimationBlock: BlockWithTraits {
public init(
animationHolder: AnimationHolder,
animatableView: Lazy<AnimatableView>,
animatableView: Lazy<AsyncSourceAnimatableView>,
widthTrait: LayoutTrait,
heightTrait: LayoutTrait
) {
@@ -1,12 +1,13 @@
import DivKitExtensions
import Foundation
import Lottie
import VGSLFundamentals
final class LottieAnimationFactory: AnimatableViewFactory {
public func createAnimatableView(
final class LottieAnimationFactory: AsyncSourceAnimatableViewFactory {
public func createAsyncSourceAnimatableView(
withMode mode: AnimationRepeatMode,
repeatCount count: Float
) -> AnimatableView {
) -> AsyncSourceAnimatableView {
let animationView = LottieAnimationView()
switch mode {
case .restart:
@@ -18,22 +19,23 @@ final class LottieAnimationFactory: AnimatableViewFactory {
}
}
extension LottieAnimationView: DivKitExtensions.AnimatableView {
extension LottieAnimationView: DivKitExtensions.AsyncSourceAnimatableView {
public func play() {
self.play(completion: nil)
self.forceDisplayUpdate()
}
public func setSource(_ source: AnimationSourceType) {
var animation: LottieAnimation?
if let source = source as? LottieAnimationSourceType {
public func setSourceAsync(_ source: AnimationSourceType) async {
guard let source = source as? LottieAnimationSourceType else {
return
}
animation = await Task(priority: .userInitiated) {
switch source {
case let .data(data):
animation = try? JSONDecoder().decode(LottieAnimation.self, from: data)
try? JSONDecoder().decode(LottieAnimation.self, from: data)
case let .json(json):
animation = try? LottieAnimation(dictionary: json)
try? LottieAnimation(dictionary: json)
}
self.animation = animation
}
}.value
}
}
@@ -66,12 +66,12 @@ final class RiveContainerView: UIView {
}
}
extension RiveContainerView: AnimatableView {
extension RiveContainerView: AsyncSourceAnimatableView {
func play() {
riveViewModel?.play(loop: loop)
}
func setSource(_ source: AnimationSourceType) {
func setSourceAsync(_ source: AnimationSourceType) async {
if let source = source as? RiveAnimationSourceType {
switch source {
case let .data(data):