From efbaeec20303cfeddb8bf1b18922eb38e89676be Mon Sep 17 00:00:00 2001 From: dmt021 Date: Thu, 5 Dec 2024 21:45:17 +0300 Subject: [PATCH] AnimatableView async setSource commit_hash:052d29b05edfe0754ab9799f7040a7e6e341760d --- .../Animations/AnimatableView.swift | 29 +++++++++++++++++-- .../Animations/AnimationBlockView.swift | 13 +++++---- .../Lottie/LottieAnimationBlock.swift | 4 +-- .../Lottie/LottieExtensionHandler.swift | 6 ++-- .../Animations/Rive/RiveAnimationBlock.swift | 4 +-- .../DivKit/LottieAnimationFactory.swift | 24 ++++++++------- .../DivKit/RiveContainerView.swift | 4 +-- 7 files changed, 57 insertions(+), 27 deletions(-) diff --git a/client/ios/DivKitExtensions/Animations/AnimatableView.swift b/client/ios/DivKitExtensions/Animations/AnimatableView.swift index d1ea3a9c1..c63443b00 100644 --- a/client/ios/DivKitExtensions/Animations/AnimatableView.swift +++ b/client/ios/DivKitExtensions/Animations/AnimatableView.swift @@ -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 diff --git a/client/ios/DivKitExtensions/Animations/AnimationBlockView.swift b/client/ios/DivKitExtensions/Animations/AnimationBlockView.swift index 05d413f84..1258029ec 100644 --- a/client/ios/DivKitExtensions/Animations/AnimationBlockView.swift +++ b/client/ios/DivKitExtensions/Animations/AnimationBlockView.swift @@ -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() + } } } } diff --git a/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift b/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift index e3302e1da..17327c89a 100644 --- a/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift +++ b/client/ios/DivKitExtensions/Animations/Lottie/LottieAnimationBlock.swift @@ -6,7 +6,7 @@ import LayoutKit import VGSL final class LottieAnimationBlock: SizeForwardingBlock { - let animatableView: Lazy + let animatableView: Lazy let animationHolder: AnimationHolder let sizeProvider: Block let scale: DivImageScale @@ -16,7 +16,7 @@ final class LottieAnimationBlock: SizeForwardingBlock { } init( - animatableView: Lazy, + animatableView: Lazy, animationHolder: AnimationHolder, sizeProvider: Block, scale: DivImageScale diff --git a/client/ios/DivKitExtensions/Animations/Lottie/LottieExtensionHandler.swift b/client/ios/DivKitExtensions/Animations/Lottie/LottieExtensionHandler.swift index df2a80721..6ff490e50 100644 --- a/client/ios/DivKitExtensions/Animations/Lottie/LottieExtensionHandler.swift +++ b/client/ios/DivKitExtensions/Animations/Lottie/LottieExtensionHandler.swift @@ -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 ) diff --git a/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift b/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift index 72369cbc1..d618dfe45 100644 --- a/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift +++ b/client/ios/DivKitExtensions/Animations/Rive/RiveAnimationBlock.swift @@ -5,7 +5,7 @@ import VGSL public final class RiveAnimationBlock: BlockWithTraits { let animationHolder: AnimationHolder - let animatableView: Lazy + let animatableView: Lazy public let widthTrait: LayoutTrait public let heightTrait: LayoutTrait @@ -15,7 +15,7 @@ public final class RiveAnimationBlock: BlockWithTraits { public init( animationHolder: AnimationHolder, - animatableView: Lazy, + animatableView: Lazy, widthTrait: LayoutTrait, heightTrait: LayoutTrait ) { diff --git a/client/ios/DivKitPlayground/DivKit/LottieAnimationFactory.swift b/client/ios/DivKitPlayground/DivKit/LottieAnimationFactory.swift index b78983505..9499ffe36 100644 --- a/client/ios/DivKitPlayground/DivKit/LottieAnimationFactory.swift +++ b/client/ios/DivKitPlayground/DivKit/LottieAnimationFactory.swift @@ -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 } } diff --git a/client/ios/DivKitPlayground/DivKit/RiveContainerView.swift b/client/ios/DivKitPlayground/DivKit/RiveContainerView.swift index e9ecbfae1..7f0dd0e3e 100644 --- a/client/ios/DivKitPlayground/DivKit/RiveContainerView.swift +++ b/client/ios/DivKitPlayground/DivKit/RiveContainerView.swift @@ -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):