diff --git a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift index 0a125cfb54..7e915c21a0 100644 --- a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift +++ b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift @@ -107,9 +107,10 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte private let animationStatusDisposable = MetaDisposable() private var progressValue: CGFloat = 0.0 + private var targetProgressValue: CGFloat = 0.0 + private var animator: ConstantDisplayLinkAnimator? private var randomCompletionStart: CGFloat = .random(in: 0.94...0.97) - private var completionProgress: Double = 0.0 private var isDone: Bool = false private var startTimestamp: Double? @@ -126,42 +127,18 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte } else if let startTimestamp = self.startTimestamp, currentTimestamp - startTimestamp < 1.0, value > 0.5 && value < 0.9 { self.randomCompletionStart = 0.8 } + + self.targetProgressValue = CGFloat(value) * self.randomCompletionStart - if let (size, isLandscape, bottomInset) = self.validLayout { - self.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.5, curve: .linear)) - } - case .done: - if let (size, isLandscape, bottomInset) = self.validLayout { - self.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut)) - } - self.animationNode.stopAtNearestLoop = true - self.animationNode.completed = { [weak self] _ in - if let strongSelf = self { - strongSelf.animationNode.visibility = false - strongSelf.doneAnimationNode.visibility = true - strongSelf.doneAnimationNode.isHidden = false - } - } - self.animationNode.frameUpdated = { [weak self] index, total in - if let strongSelf = self { - let progress = min(1.0, CGFloat(index) / CGFloat(total)) - if abs(progress - strongSelf.completionProgress) >= 0.05 || progress == 1.0 { - strongSelf.completionProgress = 0.5 * progress + if self.animator == nil { + self.animator = ConstantDisplayLinkAnimator(update: { [weak self] in + if let strongSelf = self, strongSelf.targetProgressValue > strongSelf.progressValue { + let updatedProgress = strongSelf.progressValue + 0.005 + strongSelf.progressValue = min(1.0, updatedProgress) - if let (size, isLandscape, bottomInset) = strongSelf.validLayout { - strongSelf.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut)) - } - } - } - } - self.doneAnimationNode.frameUpdated = { [weak self] index, total in - if let strongSelf = self { - let progress = 0.5 + min(1.0, CGFloat(index) / CGFloat(total) * 2.1) * 0.5 - if abs(progress - strongSelf.completionProgress) >= 0.05 || progress == 1.0 { - strongSelf.completionProgress = progress - - if progress == 1.0, !strongSelf.isDone { + if strongSelf.progressValue == 1.0 && !strongSelf.isDone { strongSelf.isDone = true + strongSelf.animator?.invalidate() if let snapshotView = strongSelf.progressTextNode.view.snapshotContentTree() { snapshotView.frame = strongSelf.progressTextNode.frame @@ -178,9 +155,36 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte } if let (size, isLandscape, bottomInset) = strongSelf.validLayout { - strongSelf.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut)) + strongSelf.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .immediate) } } + }) + self.animator?.isPaused = false + } + case .done: + if let (size, isLandscape, bottomInset) = self.validLayout { + self.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut)) + } + self.animationNode.stopAtNearestLoop = true + self.animationNode.completed = { [weak self] _ in + if let strongSelf = self { + strongSelf.animationNode.visibility = false + strongSelf.doneAnimationNode.visibility = true + strongSelf.doneAnimationNode.isHidden = false + } + } + self.animationNode.frameUpdated = { [weak self] index, total in + if let strongSelf = self { + let progress = min(1.0, CGFloat(index) / CGFloat(total)) + let delta = 1.0 - strongSelf.randomCompletionStart + strongSelf.targetProgressValue = strongSelf.randomCompletionStart + delta * progress * 0.5 + } + } + self.doneAnimationNode.frameUpdated = { [weak self] index, total in + if let strongSelf = self { + let progress = min(1.0, CGFloat(index) / CGFloat(total) * 2.1) + let delta = 1.0 - strongSelf.randomCompletionStart + strongSelf.targetProgressValue = strongSelf.randomCompletionStart + delta * 0.5 + delta * progress * 0.5 } } self.doneAnimationNode.started = { [weak self] in @@ -197,17 +201,17 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte public var completionDuration: Double { return self.elapsedTime + 3.0 + 0.15 } - + public init(theme: PresentationTheme, strings: PresentationStrings, forceNativeAppearance: Bool) { self.theme = theme self.strings = strings self.animationNode = AnimatedStickerNode() - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareProgress"), width: 256, height: 256, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareProgress"), width: 384, height: 384, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) self.animationNode.visibility = true self.doneAnimationNode = AnimatedStickerNode() - self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareDone"), width: 256, height: 256, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareDone"), width: 384, height: 384, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) self.doneAnimationNode.visibility = false self.doneAnimationNode.isHidden = true @@ -261,23 +265,13 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { self.validLayout = (size, isLandscape, bottomInset) - let nodeHeight: CGFloat = 400.0 + let nodeHeight: CGFloat = 450.0 let inset: CGFloat = 24.0 let progressHeight: CGFloat = 6.0 let spacing: CGFloat = 16.0 - var progress: CGFloat - switch self.state { - case .preparing: - progress = 0.0 - case let .progress(value): - progress = CGFloat(value) * self.randomCompletionStart - case .done: - progress = self.randomCompletionStart + (1.0 - self.randomCompletionStart) * self.completionProgress - } - self.progressValue = max(self.progressValue, progress) - progress = self.progressValue + let progress = self.progressValue let progressFrame = CGRect(x: inset, y: size.height - inset - progressHeight, width: size.width - inset * 2.0, height: progressHeight) self.progressBackgroundNode.frame = progressFrame