react-native-smooth-clip-view 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +68 -26
  2. package/android/CMakeLists.txt +0 -1
  3. package/android/build.gradle +15 -0
  4. package/android/src/main/cpp/SmoothClipAndroid.h +12 -8
  5. package/android/src/main/cpp/SmoothClipBindings.cpp +39 -15
  6. package/android/src/main/cpp/SmoothClipRegistry.cpp +288 -285
  7. package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +61 -11
  8. package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +28 -4
  9. package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +1 -0
  10. package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +180 -42
  11. package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +1 -0
  12. package/cpp/SmoothClipAnimationCurve.h +560 -0
  13. package/cpp/SmoothClipAnimationId.h +32 -0
  14. package/cpp/SmoothClipRegistry.h +11 -1
  15. package/cpp/SmoothClipVelocityTracker.h +30 -10
  16. package/ios/SmoothClipRegistry.mm +398 -150
  17. package/ios/SmoothClipTurboModule.cpp +4 -2
  18. package/ios/SmoothClipTurboModule.h +2 -1
  19. package/ios/SmoothClipView.mm +85 -140
  20. package/ios/SmoothClipViewRegistry.h +4 -1
  21. package/lib/module/NativeSmoothClipModule.js.map +1 -1
  22. package/lib/module/driverState.js +8 -0
  23. package/lib/module/driverState.js.map +1 -1
  24. package/lib/module/drivers.native.js +122 -32
  25. package/lib/module/drivers.native.js.map +1 -1
  26. package/lib/module/reactRequests.js +9 -3
  27. package/lib/module/reactRequests.js.map +1 -1
  28. package/lib/typescript/src/NativeSmoothClipModule.d.ts +1 -1
  29. package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
  30. package/lib/typescript/src/driverState.d.ts.map +1 -1
  31. package/lib/typescript/src/driverTypes.d.ts +3 -2
  32. package/lib/typescript/src/driverTypes.d.ts.map +1 -1
  33. package/lib/typescript/src/drivers.native.d.ts.map +1 -1
  34. package/lib/typescript/src/reactRequests.d.ts +3 -1
  35. package/lib/typescript/src/reactRequests.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/src/NativeSmoothClipModule.ts +2 -1
  38. package/src/driverState.ts +8 -0
  39. package/src/driverTypes.ts +3 -2
  40. package/src/drivers.native.ts +160 -29
  41. package/src/reactRequests.ts +14 -2
@@ -75,12 +75,14 @@ void SmoothClipTurboModule::setClipPresentation(
75
75
  double radius,
76
76
  double contentTranslateX,
77
77
  double contentTranslateY,
78
- bool takeOwnership) {
78
+ bool takeOwnership,
79
+ bool overridePendingAnimation) {
79
80
  const smoothclip::Presentation presentation{
80
81
  {x, y, width, height, radius}, contentTranslateX, contentTranslateY};
81
82
  if (validDriverId(driverId) && finitePresentation(presentation)) {
82
83
  smoothclip::setPresentation(
83
- static_cast<uint64_t>(driverId), presentation, takeOwnership);
84
+ static_cast<uint64_t>(driverId), presentation, takeOwnership,
85
+ overridePendingAnimation);
84
86
  }
85
87
  }
86
88
 
@@ -49,7 +49,8 @@ class SmoothClipTurboModule final
49
49
  double radius,
50
50
  double contentTranslateX,
51
51
  double contentTranslateY,
52
- bool takeOwnership);
52
+ bool takeOwnership,
53
+ bool overridePendingAnimation);
53
54
  jsi::Array beginInteraction(jsi::Runtime &runtime, double driverId);
54
55
  int32_t animateTiming(
55
56
  jsi::Runtime &runtime,
@@ -3,6 +3,7 @@
3
3
  #import "SmoothClipGeometry.h"
4
4
  #import "SmoothClipViewRegistry.h"
5
5
 
6
+ #include "SmoothClipAnimationCurve.h"
6
7
  #include "SmoothClipVelocityTracker.h"
7
8
 
8
9
  #import <QuartzCore/QuartzCore.h>
@@ -89,11 +90,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
89
90
  smoothclip::TimingAnimation _timingAnimation;
90
91
  smoothclip::SpringAnimation _springAnimation;
91
92
  SmoothClipAnimationDelegate *_animationDelegate;
92
- BOOL _animationPaused;
93
- CGRect _pausedRect;
94
- CGFloat _pausedRadius;
95
- CGPoint _pausedContentTranslation;
96
- CFTimeInterval _pausedRemaining;
97
93
 
98
94
  // 'inherit' velocity samples (normalized geometry, per view); recording/
99
95
  // coalescing/projection live in the shared cpp/SmoothClipVelocityTracker.h
@@ -150,24 +146,15 @@ static std::array<double, 7> SmoothClipVelocityChannels(
150
146
  _activeAnimationId = 0;
151
147
  _activeAnimationKind = 0;
152
148
  _pendingAnimationInstall = NO;
153
- _animationPaused = NO;
154
149
  smoothclip::clearVelocitySamples(_velocitySamples);
155
- [[NSNotificationCenter defaultCenter]
156
- addObserver:self
157
- selector:@selector(applicationWillResignActive)
158
- name:UIApplicationWillResignActiveNotification
159
- object:nil];
160
- [[NSNotificationCenter defaultCenter]
161
- addObserver:self
162
- selector:@selector(applicationDidBecomeActive)
163
- name:UIApplicationDidBecomeActiveNotification
164
- object:nil];
150
+ // App-state transitions are observed by the registry itself (see
151
+ // installApplicationStateObservers): the active flag is process-global,
152
+ // so its observer must outlive any individual view.
165
153
  }
166
154
  return self;
167
155
  }
168
156
 
169
157
  - (void)dealloc {
170
- [[NSNotificationCenter defaultCenter] removeObserver:self];
171
158
  if (_driverId != 0) {
172
159
  smoothclip::unregisterView(_driverId, self);
173
160
  }
@@ -175,8 +162,8 @@ static std::array<double, 7> SmoothClipVelocityChannels(
175
162
 
176
163
  - (void)didMoveToWindow {
177
164
  [super didMoveToWindow];
178
- if (_driverId != 0 && [self smoothClipCanDisplay]) {
179
- smoothclip::viewBecameDisplayable(_driverId, self);
165
+ if (_driverId != 0) {
166
+ smoothclip::viewDisplayabilityChanged(_driverId, self);
180
167
  }
181
168
  }
182
169
 
@@ -332,11 +319,17 @@ static std::array<double, 7> SmoothClipVelocityChannels(
332
319
  }
333
320
 
334
321
  - (void)smoothClipApplyPresentation:(smoothclip::Presentation)presentation {
335
- _animationPaused = NO;
322
+ [self smoothClipApplyPresentation:presentation recordVelocitySample:YES];
323
+ }
324
+
325
+ - (void)smoothClipApplyPresentation:(smoothclip::Presentation)presentation
326
+ recordVelocitySample:(BOOL)recordVelocitySample {
336
327
  [self stopLayerAnimationWithoutCallback];
337
328
  [self storeRequestedPresentation:presentation];
338
329
  [self applyRequestedClip];
339
- if (_hasLayout) {
330
+ // Skipped for writes that are not interactive motion (a latched
331
+ // cancel-to-target): they must not enter the 'inherit' history.
332
+ if (recordVelocitySample && _hasLayout) {
340
333
  [self recordInteractiveRect:_normalizedClip
341
334
  radius:_normalizedRadius
342
335
  contentTranslation:_normalizedContentTranslation];
@@ -366,20 +359,35 @@ static std::array<double, 7> SmoothClipVelocityChannels(
366
359
  - (BOOL)smoothClipIsJoinable {
367
360
  // A view without layout reports zero geometry from
368
361
  // smoothClipCurrentPresentation and must not be used as a join reference.
369
- return _hasLayout;
362
+ return _hasLayout && self.bounds.size.width > 0 &&
363
+ self.bounds.size.height > 0;
370
364
  }
371
365
 
372
366
  - (BOOL)smoothClipCanDisplay {
373
367
  // A CA animation committed while this view's layer tree is detached from
374
368
  // the render tree does not survive the later attach commit; installs and
375
369
  // latch starts must wait until a frame can actually be produced.
376
- return _hasLayout && self.window != nil;
370
+ return [self smoothClipIsJoinable] && self.window != nil &&
371
+ smoothclip::applicationIsActive();
377
372
  }
378
373
 
379
374
  - (BOOL)smoothClipHasPendingInstall {
380
375
  return _pendingAnimationInstall;
381
376
  }
382
377
 
378
+ - (void)smoothClipClearVelocitySamples {
379
+ smoothclip::clearVelocitySamples(_velocitySamples);
380
+ }
381
+
382
+ - (double)smoothClipSpringContinuationVelocity {
383
+ if (_activeAnimationId == 0 || _activeAnimationKind != 2 ||
384
+ _pendingAnimationInstall) {
385
+ return 0;
386
+ }
387
+ const double elapsed = MAX(0, CACurrentMediaTime() - _animationStartedAt);
388
+ return smoothclip::springContinuationVelocity(_springAnimation, elapsed);
389
+ }
390
+
383
391
  - (smoothclip::Presentation)smoothClipFreezePresentation {
384
392
  const smoothclip::Presentation visible =
385
393
  [self smoothClipCurrentPresentation];
@@ -391,7 +399,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
391
399
  const CGPoint visibleContentTranslation = CGPointMake(
392
400
  visible.contentTranslateX,
393
401
  visible.contentTranslateY);
394
- _animationPaused = NO;
395
402
  [self stopLayerAnimationWithoutCallback];
396
403
  _requestedClip = visibleRect;
397
404
  _requestedRadius = visible.clip.radius;
@@ -399,9 +406,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
399
406
  [self writeLayerRect:visibleRect radius:visible.clip.radius];
400
407
  [self writeContentTranslation:visibleContentTranslation];
401
408
  [self syncVisibilityForRect:visibleRect];
402
- [self recordInteractiveRect:visibleRect
403
- radius:visible.clip.radius
404
- contentTranslation:visibleContentTranslation];
405
409
  return visible;
406
410
  }
407
411
 
@@ -432,7 +436,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
432
436
  _ignoreAnimationCallback = NO;
433
437
  _activeAnimationId = 0;
434
438
  _activeAnimationKind = 0;
435
- _animationPaused = NO;
436
439
  _animationDelegate = nil;
437
440
  }
438
441
 
@@ -623,13 +626,13 @@ static std::array<double, 7> SmoothClipVelocityChannels(
623
626
  forKey:@"smoothClip.content"];
624
627
  }
625
628
 
626
- - (void)startAnimationToRequestedGeometryWithDuration:(CFTimeInterval)duration {
629
+ - (BOOL)startAnimationToRequestedGeometryWithDuration:(CFTimeInterval)duration {
627
630
  if (![self smoothClipCanDisplay]) {
628
631
  _pendingAnimationInstall = YES;
629
- return;
632
+ return NO;
630
633
  }
631
634
  SmoothNormalizedClipGeometry target;
632
- if (![self normalizedRequestedGeometry:&target]) return;
635
+ if (![self normalizedRequestedGeometry:&target]) return NO;
633
636
  const smoothclip::Presentation current = [self smoothClipCurrentPresentation];
634
637
  [self installAnimationFromRect:CGRectMake(
635
638
  current.clip.x,
@@ -644,20 +647,21 @@ static std::array<double, 7> SmoothClipVelocityChannels(
644
647
  toRadius:target.radius
645
648
  toContentTranslation:_requestedContentTranslation
646
649
  duration:duration];
650
+ return YES;
647
651
  }
648
652
 
649
- - (void)smoothClipAnimateTiming:(smoothclip::Presentation)presentation
653
+ - (BOOL)smoothClipAnimateTiming:(smoothclip::Presentation)presentation
650
654
  animation:(smoothclip::TimingAnimation)animation
651
655
  animationId:(int32_t)animationId {
652
656
  [self storeRequestedPresentation:presentation];
653
657
  _timingAnimation = animation;
654
658
  _activeAnimationKind = 1;
655
659
  _activeAnimationId = animationId;
656
- [self startAnimationToRequestedGeometryWithDuration:
657
- MAX(0, animation.durationMs) / 1000.0];
660
+ return [self startAnimationToRequestedGeometryWithDuration:
661
+ MAX(0, animation.durationMs) / 1000.0];
658
662
  }
659
663
 
660
- - (void)smoothClipAnimateSpring:(smoothclip::Presentation)presentation
664
+ - (BOOL)smoothClipAnimateSpring:(smoothclip::Presentation)presentation
661
665
  animation:(smoothclip::SpringAnimation)animation
662
666
  animationId:(int32_t)animationId {
663
667
  [self storeRequestedPresentation:presentation];
@@ -675,7 +679,7 @@ static std::array<double, 7> SmoothClipVelocityChannels(
675
679
  }
676
680
  _activeAnimationKind = 2;
677
681
  _activeAnimationId = animationId;
678
- [self startAnimationToRequestedGeometryWithDuration:0];
682
+ return [self startAnimationToRequestedGeometryWithDuration:0];
679
683
  }
680
684
 
681
685
  - (CAKeyframeAnimation *)keyframeAnimationForKeyPath:(NSString *)keyPath
@@ -689,17 +693,17 @@ static std::array<double, 7> SmoothClipVelocityChannels(
689
693
  return animation;
690
694
  }
691
695
 
692
- - (void)smoothClipAnimateKeyframes:(smoothclip::Presentation)presentation
696
+ - (BOOL)smoothClipAnimateKeyframes:(smoothclip::Presentation)presentation
693
697
  keyframes:(const std::vector<smoothclip::Keyframe> &)keyframes
694
698
  durationMs:(double)durationMs
695
699
  animationId:(int32_t)animationId {
696
- if (keyframes.size() < 2) return;
700
+ if (keyframes.size() < 2) return NO;
697
701
  [self storeRequestedPresentation:presentation];
698
702
  _activeAnimationKind = 3;
699
703
  _activeAnimationId = animationId;
700
704
  if (![self smoothClipCanDisplay]) {
701
705
  _pendingAnimationInstall = YES;
702
- return;
706
+ return NO;
703
707
  }
704
708
  [self stopLayerAnimationWithoutCallback];
705
709
  _activeAnimationKind = 3;
@@ -726,7 +730,7 @@ static std::array<double, 7> SmoothClipVelocityChannels(
726
730
  frame.presentation.clip.height,
727
731
  frame.presentation.clip.radius,
728
732
  hostSize,
729
- &normalized)) return;
733
+ &normalized)) return NO;
730
734
  [times addObject:@(frame.offset)];
731
735
  [boundsValues addObject:[NSValue valueWithCGRect:normalized.rect]];
732
736
  [positionValues addObject:[NSValue valueWithCGPoint:CGPointMake(
@@ -737,7 +741,7 @@ static std::array<double, 7> SmoothClipVelocityChannels(
737
741
  }
738
742
 
739
743
  SmoothNormalizedClipGeometry target;
740
- if (![self normalizedRequestedGeometry:&target]) return;
744
+ if (![self normalizedRequestedGeometry:&target]) return NO;
741
745
  [self writeLayerRect:target.rect radius:target.radius];
742
746
  [self writeContentTranslation:_requestedContentTranslation];
743
747
  [self setClipContainerHidden:NO];
@@ -776,6 +780,7 @@ static std::array<double, 7> SmoothClipVelocityChannels(
776
780
  [_clipContainer.layer addAnimation:group forKey:@"smoothClip.geometry"];
777
781
  [_contentContainer.layer addAnimation:contentGroup
778
782
  forKey:@"smoothClip.content"];
783
+ return YES;
779
784
  }
780
785
 
781
786
  - (void)smoothClipCancelAnimationUsingTarget:(BOOL)useTarget {
@@ -790,7 +795,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
790
795
  const CGPoint visibleContentTranslation = CGPointMake(
791
796
  visible.contentTranslateX,
792
797
  visible.contentTranslateY);
793
- _animationPaused = NO;
794
798
  [self stopLayerAnimationWithoutCallback];
795
799
  if (useTarget) {
796
800
  [self applyRequestedClip];
@@ -801,54 +805,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
801
805
  [self writeLayerRect:visibleRect radius:visible.clip.radius];
802
806
  [self writeContentTranslation:visibleContentTranslation];
803
807
  [self syncVisibilityForRect:visibleRect];
804
- [self recordInteractiveRect:visibleRect
805
- radius:visible.clip.radius
806
- contentTranslation:visibleContentTranslation];
807
- }
808
- }
809
-
810
- - (void)applicationWillResignActive {
811
- if (_activeAnimationId == 0 || _animationPaused) return;
812
- const smoothclip::Presentation visible =
813
- [self smoothClipCurrentPresentation];
814
- _pausedRect = CGRectMake(
815
- visible.clip.x,
816
- visible.clip.y,
817
- visible.clip.width,
818
- visible.clip.height);
819
- _pausedRadius = visible.clip.radius;
820
- _pausedContentTranslation = CGPointMake(
821
- visible.contentTranslateX,
822
- visible.contentTranslateY);
823
- _pausedRemaining = MAX(
824
- 0, _animationDuration - (CACurrentMediaTime() - _animationStartedAt));
825
- const int32_t animationId = _activeAnimationId;
826
- const NSInteger animationKind = _activeAnimationKind;
827
- [self stopLayerAnimationWithoutCallback];
828
- _activeAnimationId = animationId;
829
- _activeAnimationKind = animationKind;
830
- [self writeLayerRect:_pausedRect radius:_pausedRadius];
831
- [self writeContentTranslation:_pausedContentTranslation];
832
- _animationPaused = YES;
833
- }
834
-
835
- - (void)applicationDidBecomeActive {
836
- if (!_animationPaused || _activeAnimationId == 0) return;
837
- _animationPaused = NO;
838
- SmoothNormalizedClipGeometry target;
839
- if ([self normalizedRequestedGeometry:&target]) {
840
- if (_activeAnimationKind == 3) {
841
- _activeAnimationKind = 1;
842
- _timingAnimation = {
843
- _pausedRemaining * 1000.0, 0, 0, 1, 1, 2};
844
- }
845
- [self installAnimationFromRect:_pausedRect
846
- fromRadius:_pausedRadius
847
- fromContentTranslation:_pausedContentTranslation
848
- toRect:target.rect
849
- toRadius:target.radius
850
- toContentTranslation:_requestedContentTranslation
851
- duration:_pausedRemaining];
852
808
  }
853
809
  }
854
810
 
@@ -858,7 +814,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
858
814
  if (_ignoreAnimationCallback || animationId != _activeAnimationId) return;
859
815
  _activeAnimationId = 0;
860
816
  _activeAnimationKind = 0;
861
- _animationPaused = NO;
862
817
  _animationDelegate = nil;
863
818
  [self syncVisibilityForRect:_normalizedClip];
864
819
  smoothclip::viewAnimationDidStop(
@@ -908,31 +863,10 @@ static std::array<double, 7> SmoothClipVelocityChannels(
908
863
 
909
864
  - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
910
865
  oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics {
911
- if (!_hasLayout && _pendingAnimationInstall && _driverId != 0) {
912
- // A native animation install arrived before the first layout. Join it now
913
- // through the registry so it starts from live presentation geometry with
914
- // the true remaining duration instead of jumping to the target.
915
- [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
916
- _hasLayout = YES;
917
- [self layoutContentContainer];
918
- if (self.window == nil) {
919
- // Still detached (transparentModal subtree before presentation): an
920
- // install here would not survive the attach commit. Keep the install
921
- // pending; didMoveToWindow completes it.
922
- return;
923
- }
924
- _pendingAnimationInstall = NO;
925
- if (!smoothclip::joinActiveAnimation(_driverId, self)) {
926
- // The animation finished or was cancelled while awaiting layout.
927
- _activeAnimationId = 0;
928
- _activeAnimationKind = 0;
929
- [self applyRequestedClip];
930
- }
931
- return;
932
- }
933
866
  CGFloat visibleRadius = 0;
934
867
  const BOOL wasAnimating = _activeAnimationId != 0;
935
- const smoothclip::Presentation visible = wasAnimating
868
+ const BOOL wasPending = _pendingAnimationInstall;
869
+ const smoothclip::Presentation visible = wasAnimating && !wasPending
936
870
  ? [self smoothClipCurrentPresentation]
937
871
  : smoothclip::Presentation{{0, 0, 0, 0, 0}, 0, 0};
938
872
  const CGRect visibleRect = CGRectMake(
@@ -944,43 +878,49 @@ static std::array<double, 7> SmoothClipVelocityChannels(
944
878
  const CGPoint visibleContentTranslation = CGPointMake(
945
879
  visible.contentTranslateX,
946
880
  visible.contentTranslateY);
947
- const CFTimeInterval remaining = wasAnimating
881
+ CFTimeInterval remaining = wasAnimating
948
882
  ? MAX(0, _animationDuration -
949
883
  (CACurrentMediaTime() - _animationStartedAt))
950
884
  : 0;
885
+ const double springContinuationVelocity =
886
+ wasAnimating && !wasPending && _activeAnimationKind == 2
887
+ ? [self smoothClipSpringContinuationVelocity]
888
+ : 0;
951
889
 
952
890
  [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
953
891
  _hasLayout = YES;
954
892
  [self layoutContentContainer];
955
- if (wasAnimating && _animationPaused) {
956
- SmoothNormalizedClipGeometry paused;
957
- if (SmoothClipNormalizeGeometry(
958
- CGRectGetMinX(_pausedRect),
959
- CGRectGetMinY(_pausedRect),
960
- CGRectGetWidth(_pausedRect),
961
- CGRectGetHeight(_pausedRect),
962
- _pausedRadius,
963
- self.bounds.size,
964
- &paused)) {
965
- _pausedRect = paused.rect;
966
- _pausedRadius = paused.radius;
967
- [self writeLayerRect:paused.rect radius:paused.radius];
968
- }
969
- } else if (wasAnimating) {
970
- if (![self smoothClipCanDisplay]) {
971
- // Relayout while detached, with an animation dispatched to this view
972
- // (a transparentModal subtree resized before presentation): an install
973
- // from this commit would not survive the attach commit. Keep the
974
- // install deferred; didMoveToWindow completes it via the registry join.
975
- _pendingAnimationInstall = YES;
976
- return;
977
- }
893
+ if (_driverId != 0) {
894
+ // Both edges matter: zero size/detach/background suspend an installed
895
+ // participant; the first positive visible layout resumes the held latch.
896
+ smoothclip::viewDisplayabilityChanged(_driverId, self);
897
+ }
898
+ if (wasPending) {
899
+ // The registry either kept the install deferred or installed the rebased
900
+ // latch. Relayout must not independently restart a background-held id.
901
+ if (_activeAnimationId == 0) [self applyRequestedClip];
902
+ return;
903
+ }
904
+ if (wasAnimating) {
905
+ // A negative transition may have frozen this host and re-latched the
906
+ // registry above. Its non-recording freeze is already the correct model
907
+ // state for the new lifecycle; do not resurrect a local timer.
908
+ if (_activeAnimationId == 0 || ![self smoothClipCanDisplay]) return;
978
909
  const int32_t animationId = _activeAnimationId;
979
910
  const NSInteger animationKind = _activeAnimationKind;
980
911
  [self stopLayerAnimationWithoutCallback];
981
912
  _activeAnimationId = animationId;
982
913
  _activeAnimationKind = animationKind;
983
- if (_activeAnimationKind == 3) {
914
+ if (_activeAnimationKind == 1 && _animationDuration > 0) {
915
+ const double progress = smoothclip::clamp01(
916
+ 1 - remaining / _animationDuration);
917
+ _timingAnimation =
918
+ smoothclip::timingRemainder(_timingAnimation, progress).animation;
919
+ remaining = _timingAnimation.durationMs / 1000.0;
920
+ } else if (_activeAnimationKind == 2) {
921
+ _springAnimation.initialVelocity = springContinuationVelocity;
922
+ _springAnimation.inheritVelocity = false;
923
+ } else if (_activeAnimationKind == 3) {
984
924
  _activeAnimationKind = 1;
985
925
  _timingAnimation = {remaining * 1000.0, 0, 0, 1, 1, 2};
986
926
  }
@@ -1004,6 +944,12 @@ static std::array<double, 7> SmoothClipVelocityChannels(
1004
944
  duration:remaining];
1005
945
  }
1006
946
  } else {
947
+ if (_driverId != 0 && smoothclip::hasActiveAnimation(_driverId)) {
948
+ // Registry-level lifecycle pause owns the frozen model. A layout pass
949
+ // while its latch is held must not apply the requested target or start a
950
+ // per-view timer; foreground/reattach will normalize and resume it once.
951
+ return;
952
+ }
1007
953
  [self applyRequestedClip];
1008
954
  }
1009
955
  }
@@ -1071,7 +1017,6 @@ static std::array<double, 7> SmoothClipVelocityChannels(
1071
1017
  }
1072
1018
  [self stopLayerAnimationWithoutCallback];
1073
1019
  _pendingAnimationInstall = NO;
1074
- _animationPaused = NO;
1075
1020
  smoothclip::clearVelocitySamples(_velocitySamples);
1076
1021
  [super prepareForRecycle];
1077
1022
  _requestedClip = CGRectZero;
@@ -23,7 +23,10 @@ bool joinActiveAnimation(uint64_t driverId, SmoothClipView *view);
23
23
  // A CA animation committed while the host's layer tree is detached (e.g. a
24
24
  // transparentModal subtree before its view controller is presented) does not
25
25
  // survive the attach commit; installs must therefore wait for this signal.
26
- void viewBecameDisplayable(uint64_t driverId, SmoothClipView *view);
26
+ void viewDisplayabilityChanged(uint64_t driverId, SmoothClipView *view);
27
+ void applicationWillResignActive();
28
+ void applicationDidBecomeActive();
29
+ bool applicationIsActive();
27
30
  void viewAnimationDidStop(
28
31
  uint64_t driverId,
29
32
  int32_t animationId,
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSmoothClipModule.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAsGlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,wBAAwB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSmoothClipModule.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAuGlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,wBAAwB,CAAC","ignoreList":[]}
@@ -24,6 +24,14 @@ export function detachDriverState(state) {
24
24
  if (statesById.get(state.driverId) === state) {
25
25
  statesById.delete(state.driverId);
26
26
  }
27
+ // Requests pending at teardown were settled by rejectDriverRequests, but
28
+ // their completion deferrals can no longer be released: the late-scheduled
29
+ // resolver's releaseDriverCompletions no-ops against a detached state. An
30
+ // effect replay reattaches THIS same object, so a stale positive count
31
+ // would queue every future completion forever. The deferrals died with
32
+ // their requests — reset them.
33
+ state.completionDeferrals = 0;
34
+ state.deferredCompletions.length = 0;
27
35
  }
28
36
  export function createDriverState(driverId, initialPresentation, source, onAnimationComplete, activeAnimationId, ownership) {
29
37
  return {
@@ -1 +1 @@
1
- {"version":3,"names":["states","WeakMap","statesById","Map","nextDriverId","Date","now","allocateDriverId","Number","isSafeInteger","setDriverState","driver","state","set","attachDriverState","driverId","detachDriverState","get","delete","createDriverState","initialPresentation","source","onAnimationComplete","activeAnimationId","ownership","mountedViews","Set","animationParticipants","failedAnimations","completionDeferrals","deferredCompletions","registerDriverView","getDriverState","token","add","animationId","participants","has","snapshotDriverViews","finishDriverAnimation","finished","result","deliverDriverCompletion","push","current","deferDriverCompletions","releaseDriverCompletions","deferred","splice","Error"],"sourceRoot":"../../src","sources":["driverState.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["states","WeakMap","statesById","Map","nextDriverId","Date","now","allocateDriverId","Number","isSafeInteger","setDriverState","driver","state","set","attachDriverState","driverId","detachDriverState","get","delete","completionDeferrals","deferredCompletions","length","createDriverState","initialPresentation","source","onAnimationComplete","activeAnimationId","ownership","mountedViews","Set","animationParticipants","failedAnimations","registerDriverView","getDriverState","token","add","animationId","participants","has","snapshotDriverViews","finishDriverAnimation","finished","result","deliverDriverCompletion","push","current","deferDriverCompletions","releaseDriverCompletions","deferred","splice","Error"],"sourceRoot":"../../src","sources":["driverState.ts"],"mappings":"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","ignoreList":[]}