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
@@ -27,9 +27,16 @@ struct VelocitySampleHistory {
27
27
  // batch spacing and below the 8.33 ms 120 Hz frame, so legitimate
28
28
  // consecutive-frame samples never coalesce.
29
29
  inline constexpr double kSampleCoalesceWindowS = 0.004;
30
- // A latest sample older than this no longer describes the finger; 'inherit'
31
- // yields zero instead of replaying stale motion.
30
+ // A latest sample this old no longer describes the finger at all; 'inherit'
31
+ // yields zero rather than replaying stale motion. It is the far end of the
32
+ // decay below, not a cliff.
32
33
  inline constexpr double kVelocityStalenessS = 0.1;
34
+ // Below this age the sample is still "now": an ordinary fling calls animateTo
35
+ // in the same input batch as, or one frame after, the last drag write, and
36
+ // must inherit its motion undiminished. Decaying from zero age instead would
37
+ // shave ~17% off every normal handoff at 60 Hz — a regression in the case that
38
+ // matters most, in exchange for fixing the case that barely happens.
39
+ inline constexpr double kVelocityFullCreditS = 1.0 / 60.0;
33
40
 
34
41
  inline void recordVelocitySample(
35
42
  VelocitySampleHistory &history,
@@ -60,17 +67,29 @@ inline void recordVelocitySample(
60
67
  history.latestTimeS = nowS;
61
68
  }
62
69
 
63
- // beginInteraction on both platforms records the frozen presentation as a
64
- // plain sample: a grab mid-animation pairs the frozen value with the last
65
- // real sample, so an instant refling inherits bounded recent motion instead
66
- // of launching dead, and a grab at an unchanged value dedupes to a no-op
67
- // whose staleness keeps aging. There is deliberately no reset primitive —
68
- // the 100 ms staleness guard is the forgetting mechanism.
70
+ // Only explicit interactive writes route through this recorder. Native
71
+ // freeze/join/resume/static-finalization paths deliberately do not, so an
72
+ // animation cannot manufacture a later inherited velocity. During ordinary
73
+ // interaction, the staleness decay below is the forgetting mechanism and it
74
+ // forgets gradually rather than all at once.
69
75
 
70
76
  inline void clearVelocitySamples(VelocitySampleHistory &history) {
71
77
  history = VelocitySampleHistory{};
72
78
  }
73
79
 
80
+ // Age of the newest sample expressed as a credit multiplier: full inside the
81
+ // grace window, decaying linearly to zero at the staleness bound. The old
82
+ // binary cutoff meant a release after a 99 ms still-hold launched at the full
83
+ // drag velocity while 101 ms launched dead — a step the hand can feel, and one
84
+ // RNGH's own windowed event.velocity* does not have. Continuous and monotone
85
+ // in holdS, so no hold duration produces a discontinuity in launch speed.
86
+ inline double velocityStalenessCredit(double holdS) {
87
+ if (holdS <= kVelocityFullCreditS) return 1;
88
+ if (holdS >= kVelocityStalenessS) return 0;
89
+ return (kVelocityStalenessS - holdS) /
90
+ (kVelocityStalenessS - kVelocityFullCreditS);
91
+ }
92
+
74
93
  // Normalized velocity of the recorded motion projected onto the
75
94
  // latest→target trajectory, in units of remaining-distance per second
76
95
  // (1 covers the remaining distance in one second) — the CASpringAnimation
@@ -82,7 +101,8 @@ inline double inheritedVelocity(
82
101
  double nowS) {
83
102
  if (!history.hasPrevious || !history.hasLatest) return 0;
84
103
  const double elapsed = history.latestTimeS - history.previousTimeS;
85
- if (elapsed <= 0 || nowS - history.latestTimeS > kVelocityStalenessS) {
104
+ const double credit = velocityStalenessCredit(nowS - history.latestTimeS);
105
+ if (elapsed <= 0 || credit <= 0) {
86
106
  return 0;
87
107
  }
88
108
  double numerator = 0;
@@ -94,7 +114,7 @@ inline double inheritedVelocity(
94
114
  denominator += destinationDelta * destinationDelta;
95
115
  }
96
116
  if (denominator <= 1e-12) return 0;
97
- const double result = numerator / elapsed / denominator;
117
+ const double result = numerator / elapsed / denominator * credit;
98
118
  return std::isfinite(result) ? result : 0;
99
119
  }
100
120