react-native-smooth-clip-view 0.2.9 → 0.4.0

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 (193) hide show
  1. package/README.md +132 -349
  2. package/android/build.gradle +8 -4
  3. package/android/proguard-rules.pro +3 -3
  4. package/android/src/main/cpp/SmoothClipAndroid.h +13 -6
  5. package/android/src/main/cpp/SmoothClipBindings.cpp +605 -123
  6. package/android/src/main/cpp/SmoothClipRegistry.cpp +975 -209
  7. package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +192 -118
  8. package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +22 -4
  9. package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +81 -56
  10. package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +449 -240
  11. package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +150 -38
  12. package/cpp/SmoothClipAnimationCurve.h +317 -397
  13. package/cpp/SmoothClipRegistry.h +84 -20
  14. package/cpp/SmoothClipSharedGeometry.h +131 -22
  15. package/cpp/SmoothClipVelocityTracker.h +16 -12
  16. package/ios/SmoothClipGeometry.h +188 -21
  17. package/ios/SmoothClipRegistry.mm +869 -368
  18. package/ios/SmoothClipRegistrySnapshot.h +13 -0
  19. package/ios/SmoothClipTurboModule.cpp +513 -156
  20. package/ios/SmoothClipTurboModule.h +123 -56
  21. package/ios/SmoothClipView.mm +1074 -449
  22. package/ios/SmoothClipViewRegistry.h +3 -7
  23. package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  24. package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  25. package/lib/module/NativeSmoothClipModule.js.map +1 -1
  26. package/lib/module/SmoothClipView.ios.js +94 -11
  27. package/lib/module/SmoothClipView.ios.js.map +1 -1
  28. package/lib/module/SmoothClipView.js +1 -46
  29. package/lib/module/SmoothClipView.js.map +1 -1
  30. package/lib/module/SmoothClipViewNativeComponent.ts +32 -12
  31. package/lib/module/capabilities.js +4 -0
  32. package/lib/module/capabilities.js.map +1 -0
  33. package/lib/module/capabilities.native.js +18 -0
  34. package/lib/module/capabilities.native.js.map +1 -0
  35. package/lib/module/capabilityTypes.js +2 -0
  36. package/lib/module/capabilityTypes.js.map +1 -0
  37. package/lib/module/controllerInternals.js +28 -0
  38. package/lib/module/controllerInternals.js.map +1 -0
  39. package/lib/module/controllerLifecycle.js +9 -0
  40. package/lib/module/controllerLifecycle.js.map +1 -0
  41. package/lib/module/controllerTypes.js +4 -0
  42. package/lib/module/controllerTypes.js.map +1 -0
  43. package/lib/module/controllers.android.js +4 -0
  44. package/lib/module/controllers.android.js.map +1 -0
  45. package/lib/module/controllers.ios.js +4 -0
  46. package/lib/module/controllers.ios.js.map +1 -0
  47. package/lib/module/controllers.js +4 -0
  48. package/lib/module/controllers.js.map +1 -0
  49. package/lib/module/controllers.native.js +89 -0
  50. package/lib/module/controllers.native.js.map +1 -0
  51. package/lib/module/geometry.js +180 -30
  52. package/lib/module/geometry.js.map +1 -1
  53. package/lib/module/groupTypes.js +4 -0
  54. package/lib/module/groupTypes.js.map +1 -0
  55. package/lib/module/groups.android.js +4 -0
  56. package/lib/module/groups.android.js.map +1 -0
  57. package/lib/module/groups.ios.js +4 -0
  58. package/lib/module/groups.ios.js.map +1 -0
  59. package/lib/module/groups.js +4 -0
  60. package/lib/module/groups.js.map +1 -0
  61. package/lib/module/groups.native.js +399 -0
  62. package/lib/module/groups.native.js.map +1 -0
  63. package/lib/module/ids.js +8 -0
  64. package/lib/module/ids.js.map +1 -0
  65. package/lib/module/index.js +4 -3
  66. package/lib/module/index.js.map +1 -1
  67. package/lib/module/nativeCompletion.js +37 -16
  68. package/lib/module/nativeCompletion.js.map +1 -1
  69. package/lib/module/presentationCodec.js +81 -0
  70. package/lib/module/presentationCodec.js.map +1 -0
  71. package/lib/typescript/src/NativeSmoothClipModule.d.ts +20 -4
  72. package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
  73. package/lib/typescript/src/SmoothClipView.d.ts +2 -10
  74. package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
  75. package/lib/typescript/src/SmoothClipView.ios.d.ts +139 -4
  76. package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
  77. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +16 -3
  78. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
  79. package/lib/typescript/src/capabilities.d.ts +3 -0
  80. package/lib/typescript/src/capabilities.d.ts.map +1 -0
  81. package/lib/typescript/src/capabilities.native.d.ts +3 -0
  82. package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
  83. package/lib/typescript/src/capabilityTypes.d.ts +4 -0
  84. package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
  85. package/lib/typescript/src/controllerInternals.d.ts +14 -0
  86. package/lib/typescript/src/controllerInternals.d.ts.map +1 -0
  87. package/lib/typescript/src/controllerLifecycle.d.ts +3 -0
  88. package/lib/typescript/src/controllerLifecycle.d.ts.map +1 -0
  89. package/lib/typescript/src/controllerTypes.d.ts +62 -0
  90. package/lib/typescript/src/controllerTypes.d.ts.map +1 -0
  91. package/lib/typescript/src/controllers.android.d.ts +2 -0
  92. package/lib/typescript/src/controllers.android.d.ts.map +1 -0
  93. package/lib/typescript/src/controllers.d.ts +2 -0
  94. package/lib/typescript/src/controllers.d.ts.map +1 -0
  95. package/lib/typescript/src/controllers.ios.d.ts +2 -0
  96. package/lib/typescript/src/controllers.ios.d.ts.map +1 -0
  97. package/lib/typescript/src/controllers.native.d.ts +3 -0
  98. package/lib/typescript/src/controllers.native.d.ts.map +1 -0
  99. package/lib/typescript/src/geometry.d.ts +49 -5
  100. package/lib/typescript/src/geometry.d.ts.map +1 -1
  101. package/lib/typescript/src/groupTypes.d.ts +31 -0
  102. package/lib/typescript/src/groupTypes.d.ts.map +1 -0
  103. package/lib/typescript/src/groups.android.d.ts +2 -0
  104. package/lib/typescript/src/groups.android.d.ts.map +1 -0
  105. package/lib/typescript/src/groups.d.ts +2 -0
  106. package/lib/typescript/src/groups.d.ts.map +1 -0
  107. package/lib/typescript/src/groups.ios.d.ts +2 -0
  108. package/lib/typescript/src/groups.ios.d.ts.map +1 -0
  109. package/lib/typescript/src/groups.native.d.ts +3 -0
  110. package/lib/typescript/src/groups.native.d.ts.map +1 -0
  111. package/lib/typescript/src/ids.d.ts +2 -0
  112. package/lib/typescript/src/ids.d.ts.map +1 -0
  113. package/lib/typescript/src/index.d.ts +8 -5
  114. package/lib/typescript/src/index.d.ts.map +1 -1
  115. package/lib/typescript/src/nativeCompletion.d.ts +16 -6
  116. package/lib/typescript/src/nativeCompletion.d.ts.map +1 -1
  117. package/lib/typescript/src/presentationCodec.d.ts +10 -0
  118. package/lib/typescript/src/presentationCodec.d.ts.map +1 -0
  119. package/package.json +17 -13
  120. package/src/NativeSmoothClipModule.ts +80 -56
  121. package/src/SmoothClipView.ios.tsx +142 -16
  122. package/src/SmoothClipView.tsx +6 -76
  123. package/src/SmoothClipViewNativeComponent.ts +32 -12
  124. package/src/capabilities.native.ts +19 -0
  125. package/src/capabilities.ts +2 -0
  126. package/src/capabilityTypes.ts +3 -0
  127. package/src/controllerInternals.ts +52 -0
  128. package/src/controllerLifecycle.ts +6 -0
  129. package/src/controllerTypes.ts +87 -0
  130. package/src/controllers.android.ts +1 -0
  131. package/src/controllers.ios.ts +1 -0
  132. package/src/controllers.native.ts +104 -0
  133. package/src/controllers.ts +1 -0
  134. package/src/geometry.ts +293 -45
  135. package/src/groupTypes.ts +53 -0
  136. package/src/groups.android.ts +1 -0
  137. package/src/groups.ios.ts +1 -0
  138. package/src/groups.native.ts +604 -0
  139. package/src/groups.ts +1 -0
  140. package/src/ids.ts +6 -0
  141. package/src/index.ts +32 -12
  142. package/src/nativeCompletion.ts +67 -32
  143. package/src/presentationCodec.ts +134 -0
  144. package/lib/module/SmoothClipView.web.js +0 -54
  145. package/lib/module/SmoothClipView.web.js.map +0 -1
  146. package/lib/module/driverState.js +0 -110
  147. package/lib/module/driverState.js.map +0 -1
  148. package/lib/module/driverTypes.js +0 -4
  149. package/lib/module/driverTypes.js.map +0 -1
  150. package/lib/module/drivers.android.js +0 -6
  151. package/lib/module/drivers.android.js.map +0 -1
  152. package/lib/module/drivers.ios.js +0 -6
  153. package/lib/module/drivers.ios.js.map +0 -1
  154. package/lib/module/drivers.js +0 -284
  155. package/lib/module/drivers.js.map +0 -1
  156. package/lib/module/drivers.native.js +0 -556
  157. package/lib/module/drivers.native.js.map +0 -1
  158. package/lib/module/index.web.js +0 -8
  159. package/lib/module/index.web.js.map +0 -1
  160. package/lib/module/reactRequests.js +0 -56
  161. package/lib/module/reactRequests.js.map +0 -1
  162. package/lib/module/webClipPath.js +0 -25
  163. package/lib/module/webClipPath.js.map +0 -1
  164. package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
  165. package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
  166. package/lib/typescript/src/driverState.d.ts +0 -31
  167. package/lib/typescript/src/driverState.d.ts.map +0 -1
  168. package/lib/typescript/src/driverTypes.d.ts +0 -107
  169. package/lib/typescript/src/driverTypes.d.ts.map +0 -1
  170. package/lib/typescript/src/drivers.android.d.ts +0 -3
  171. package/lib/typescript/src/drivers.android.d.ts.map +0 -1
  172. package/lib/typescript/src/drivers.d.ts +0 -5
  173. package/lib/typescript/src/drivers.d.ts.map +0 -1
  174. package/lib/typescript/src/drivers.ios.d.ts +0 -3
  175. package/lib/typescript/src/drivers.ios.d.ts.map +0 -1
  176. package/lib/typescript/src/drivers.native.d.ts +0 -5
  177. package/lib/typescript/src/drivers.native.d.ts.map +0 -1
  178. package/lib/typescript/src/index.web.d.ts +0 -9
  179. package/lib/typescript/src/index.web.d.ts.map +0 -1
  180. package/lib/typescript/src/reactRequests.d.ts +0 -9
  181. package/lib/typescript/src/reactRequests.d.ts.map +0 -1
  182. package/lib/typescript/src/webClipPath.d.ts +0 -7
  183. package/lib/typescript/src/webClipPath.d.ts.map +0 -1
  184. package/src/SmoothClipView.web.tsx +0 -66
  185. package/src/driverState.ts +0 -158
  186. package/src/driverTypes.ts +0 -140
  187. package/src/drivers.android.ts +0 -8
  188. package/src/drivers.ios.ts +0 -8
  189. package/src/drivers.native.ts +0 -899
  190. package/src/drivers.ts +0 -427
  191. package/src/index.web.ts +0 -23
  192. package/src/reactRequests.ts +0 -76
  193. package/src/webClipPath.ts +0 -30
@@ -1,6 +1,8 @@
1
1
  #include "SmoothClipTurboModule.h"
2
2
 
3
+ #include "SmoothClipAnimationCurve.h"
3
4
  #include "SmoothClipRegistry.h"
5
+ #include "SmoothClipRegistrySnapshot.h"
4
6
 
5
7
  #include <cmath>
6
8
  #include <utility>
@@ -8,6 +10,10 @@
8
10
  namespace facebook::react {
9
11
  namespace {
10
12
 
13
+ constexpr size_t kPresentationStride = 21;
14
+ constexpr size_t kSnapshotStride = kPresentationStride + 1;
15
+ constexpr size_t kMotionEntryStride = kPresentationStride * 2 + 2;
16
+
11
17
  constexpr double kMaxSafeJavaScriptInteger = 9007199254740991.0;
12
18
 
13
19
  bool validDriverId(double value) {
@@ -21,10 +27,257 @@ bool finiteGeometry(const smoothclip::Geometry &geometry) {
21
27
  std::isfinite(geometry.radius);
22
28
  }
23
29
 
30
+ bool validCurveCode(int32_t curveCode) {
31
+ return curveCode == static_cast<int32_t>(smoothclip::ClipCurve::Circular) ||
32
+ curveCode == static_cast<int32_t>(smoothclip::ClipCurve::Continuous);
33
+ }
34
+
35
+ bool numberAt(
36
+ jsi::Runtime &runtime,
37
+ const jsi::Array &array,
38
+ size_t index,
39
+ double &result) {
40
+ if (index >= array.size(runtime)) return false;
41
+ const jsi::Value value = array.getValueAtIndex(runtime, index);
42
+ if (!value.isNumber()) return false;
43
+ result = value.asNumber();
44
+ return std::isfinite(result);
45
+ }
46
+
47
+ smoothclip::Presentation makePresentation(
48
+ double x,
49
+ double y,
50
+ double width,
51
+ double height,
52
+ double topLeftRadius,
53
+ double topRightRadius,
54
+ double bottomRightRadius,
55
+ double bottomLeftRadius,
56
+ int32_t curveCode,
57
+ double contentTranslateX,
58
+ double contentTranslateY,
59
+ double contentScale,
60
+ bool shadowEnabled = false,
61
+ double shadowRed = 0,
62
+ double shadowGreen = 0,
63
+ double shadowBlue = 0,
64
+ double shadowAlpha = 1,
65
+ double shadowOffsetX = 0,
66
+ double shadowOffsetY = 0,
67
+ double shadowBlurRadius = 0,
68
+ double shadowSpreadDistance = 0) {
69
+ const bool uniform = topLeftRadius == topRightRadius &&
70
+ topLeftRadius == bottomRightRadius &&
71
+ topLeftRadius == bottomLeftRadius;
72
+ smoothclip::Geometry geometry{
73
+ x, y, width, height, uniform ? topLeftRadius : 0};
74
+ geometry.topLeftRadius = topLeftRadius;
75
+ geometry.topRightRadius = topRightRadius;
76
+ geometry.bottomRightRadius = bottomRightRadius;
77
+ geometry.bottomLeftRadius = bottomLeftRadius;
78
+ geometry.curve = static_cast<smoothclip::ClipCurve>(curveCode);
79
+ return {
80
+ geometry,
81
+ contentTranslateX,
82
+ contentTranslateY,
83
+ contentScale,
84
+ {shadowEnabled, shadowRed, shadowGreen, shadowBlue, shadowAlpha,
85
+ shadowOffsetX, shadowOffsetY, shadowBlurRadius, shadowSpreadDistance}};
86
+ }
87
+
24
88
  bool finitePresentation(const smoothclip::Presentation &presentation) {
25
- return finiteGeometry(presentation.clip) &&
89
+ const smoothclip::Geometry &geometry = presentation.clip;
90
+ return finiteGeometry(geometry) &&
91
+ std::isfinite(geometry.topLeftRadius) &&
92
+ std::isfinite(geometry.topRightRadius) &&
93
+ std::isfinite(geometry.bottomRightRadius) &&
94
+ std::isfinite(geometry.bottomLeftRadius) &&
95
+ validCurveCode(static_cast<int32_t>(geometry.curve)) &&
26
96
  std::isfinite(presentation.contentTranslateX) &&
27
- std::isfinite(presentation.contentTranslateY);
97
+ std::isfinite(presentation.contentTranslateY) &&
98
+ std::isfinite(presentation.contentScale) &&
99
+ presentation.contentScale > 0 &&
100
+ std::isfinite(presentation.shadow.red) &&
101
+ std::isfinite(presentation.shadow.green) &&
102
+ std::isfinite(presentation.shadow.blue) &&
103
+ std::isfinite(presentation.shadow.alpha) &&
104
+ std::isfinite(presentation.shadow.offsetX) &&
105
+ std::isfinite(presentation.shadow.offsetY) &&
106
+ std::isfinite(presentation.shadow.blurRadius) &&
107
+ std::isfinite(presentation.shadow.spreadDistance) &&
108
+ presentation.shadow.red >= 0 && presentation.shadow.red <= 1 &&
109
+ presentation.shadow.green >= 0 && presentation.shadow.green <= 1 &&
110
+ presentation.shadow.blue >= 0 && presentation.shadow.blue <= 1 &&
111
+ presentation.shadow.alpha >= 0 && presentation.shadow.alpha <= 1 &&
112
+ presentation.shadow.blurRadius >= 0;
113
+ }
114
+
115
+ bool presentationAt(
116
+ jsi::Runtime &runtime,
117
+ const jsi::Array &array,
118
+ size_t offset,
119
+ smoothclip::Presentation &result) {
120
+ double values[kPresentationStride];
121
+ for (size_t index = 0; index < kPresentationStride; index += 1) {
122
+ if (!numberAt(runtime, array, offset + index, values[index])) {
123
+ return false;
124
+ }
125
+ }
126
+ const int32_t curveCode = static_cast<int32_t>(values[8]);
127
+ if (values[8] != curveCode || !validCurveCode(curveCode) ||
128
+ (values[12] != 0 && values[12] != 1)) return false;
129
+ result = makePresentation(
130
+ values[0],
131
+ values[1],
132
+ values[2],
133
+ values[3],
134
+ values[4],
135
+ values[5],
136
+ values[6],
137
+ values[7],
138
+ curveCode,
139
+ values[9],
140
+ values[10],
141
+ values[11],
142
+ values[12] == 1,
143
+ values[13], values[14], values[15], values[16],
144
+ values[17], values[18], values[19], values[20]);
145
+ return finitePresentation(result);
146
+ }
147
+
148
+ void writePresentation(
149
+ jsi::Runtime &runtime,
150
+ jsi::Array &result,
151
+ size_t offset,
152
+ const smoothclip::Presentation &presentation) {
153
+ const smoothclip::Geometry &clip = presentation.clip;
154
+ result.setValueAtIndex(runtime, offset, clip.x);
155
+ result.setValueAtIndex(runtime, offset + 1, clip.y);
156
+ result.setValueAtIndex(runtime, offset + 2, clip.width);
157
+ result.setValueAtIndex(runtime, offset + 3, clip.height);
158
+ result.setValueAtIndex(
159
+ runtime, offset + 4,
160
+ smoothclip::resolvedRadius(clip.topLeftRadius, clip.radius));
161
+ result.setValueAtIndex(
162
+ runtime, offset + 5,
163
+ smoothclip::resolvedRadius(clip.topRightRadius, clip.radius));
164
+ result.setValueAtIndex(
165
+ runtime, offset + 6,
166
+ smoothclip::resolvedRadius(clip.bottomRightRadius, clip.radius));
167
+ result.setValueAtIndex(
168
+ runtime, offset + 7,
169
+ smoothclip::resolvedRadius(clip.bottomLeftRadius, clip.radius));
170
+ result.setValueAtIndex(
171
+ runtime, offset + 8, static_cast<int32_t>(clip.curve));
172
+ result.setValueAtIndex(runtime, offset + 9, presentation.contentTranslateX);
173
+ result.setValueAtIndex(runtime, offset + 10, presentation.contentTranslateY);
174
+ result.setValueAtIndex(runtime, offset + 11, presentation.contentScale);
175
+ result.setValueAtIndex(runtime, offset + 12, presentation.shadow.enabled ? 1.0 : 0.0);
176
+ result.setValueAtIndex(runtime, offset + 13, presentation.shadow.red);
177
+ result.setValueAtIndex(runtime, offset + 14, presentation.shadow.green);
178
+ result.setValueAtIndex(runtime, offset + 15, presentation.shadow.blue);
179
+ result.setValueAtIndex(runtime, offset + 16, presentation.shadow.alpha);
180
+ result.setValueAtIndex(runtime, offset + 17, presentation.shadow.offsetX);
181
+ result.setValueAtIndex(runtime, offset + 18, presentation.shadow.offsetY);
182
+ result.setValueAtIndex(runtime, offset + 19, presentation.shadow.blurRadius);
183
+ result.setValueAtIndex(runtime, offset + 20, presentation.shadow.spreadDistance);
184
+ }
185
+
186
+ jsi::Array snapshotArray(
187
+ jsi::Runtime &runtime,
188
+ const std::vector<smoothclip::DriverSnapshot> &snapshots) {
189
+ jsi::Array result(runtime, snapshots.size() * kSnapshotStride);
190
+ for (size_t index = 0; index < snapshots.size(); index += 1) {
191
+ const size_t offset = index * kSnapshotStride;
192
+ result.setValueAtIndex(
193
+ runtime, offset, snapshots[index].ready ? 1.0 : 0.0);
194
+ writePresentation(
195
+ runtime, result, offset + 1, snapshots[index].presentation);
196
+ }
197
+ return result;
198
+ }
199
+
200
+ std::vector<double> snapshotValues(
201
+ const std::vector<smoothclip::DriverSnapshot> &snapshots) {
202
+ std::vector<double> result;
203
+ result.reserve(snapshots.size() * kSnapshotStride);
204
+ for (const smoothclip::DriverSnapshot &snapshot : snapshots) {
205
+ const smoothclip::Presentation &presentation = snapshot.presentation;
206
+ result.push_back(snapshot.ready ? 1.0 : 0.0);
207
+ result.push_back(presentation.clip.x);
208
+ result.push_back(presentation.clip.y);
209
+ result.push_back(presentation.clip.width);
210
+ result.push_back(presentation.clip.height);
211
+ result.push_back(presentation.clip.topLeftRadius);
212
+ result.push_back(presentation.clip.topRightRadius);
213
+ result.push_back(presentation.clip.bottomRightRadius);
214
+ result.push_back(presentation.clip.bottomLeftRadius);
215
+ result.push_back(
216
+ presentation.clip.curve == smoothclip::ClipCurve::Continuous ? 1.0 : 0.0);
217
+ result.push_back(presentation.contentTranslateX);
218
+ result.push_back(presentation.contentTranslateY);
219
+ result.push_back(presentation.contentScale);
220
+ result.push_back(presentation.shadow.enabled ? 1.0 : 0.0);
221
+ result.push_back(presentation.shadow.red);
222
+ result.push_back(presentation.shadow.green);
223
+ result.push_back(presentation.shadow.blue);
224
+ result.push_back(presentation.shadow.alpha);
225
+ result.push_back(presentation.shadow.offsetX);
226
+ result.push_back(presentation.shadow.offsetY);
227
+ result.push_back(presentation.shadow.blurRadius);
228
+ result.push_back(presentation.shadow.spreadDistance);
229
+ }
230
+ return result;
231
+ }
232
+
233
+ bool driverIdsAt(
234
+ jsi::Runtime &runtime,
235
+ const jsi::Array &array,
236
+ std::vector<uint64_t> &result) {
237
+ result.clear();
238
+ result.reserve(array.size(runtime));
239
+ for (size_t index = 0; index < array.size(runtime); index += 1) {
240
+ double driverId = 0;
241
+ if (!numberAt(runtime, array, index, driverId) ||
242
+ !validDriverId(driverId)) {
243
+ return false;
244
+ }
245
+ result.push_back(static_cast<uint64_t>(driverId));
246
+ }
247
+ return true;
248
+ }
249
+
250
+ bool fixedGroupEntriesAt(
251
+ jsi::Runtime &runtime,
252
+ const jsi::Array &array,
253
+ std::vector<smoothclip::GroupMotionEntry> &result) {
254
+ constexpr size_t stride = kMotionEntryStride;
255
+ const size_t count = array.size(runtime);
256
+ if (count == 0 || count % stride != 0) return false;
257
+ result.clear();
258
+ result.reserve(count / stride);
259
+ for (size_t offset = 0; offset < count; offset += stride) {
260
+ double rawDriverId = 0;
261
+ double rawHasFrom = 0;
262
+ smoothclip::Presentation from;
263
+ smoothclip::Presentation target;
264
+ if (!numberAt(runtime, array, offset, rawDriverId) ||
265
+ !validDriverId(rawDriverId) ||
266
+ !numberAt(runtime, array, offset + 1, rawHasFrom) ||
267
+ (rawHasFrom != 0 && rawHasFrom != 1) ||
268
+ !presentationAt(runtime, array, offset + 2, from) ||
269
+ !presentationAt(
270
+ runtime, array, offset + 2 + kPresentationStride, target)) {
271
+ return false;
272
+ }
273
+ result.push_back({
274
+ static_cast<uint64_t>(rawDriverId),
275
+ rawHasFrom == 1,
276
+ from,
277
+ target,
278
+ });
279
+ }
280
+ return true;
28
281
  }
29
282
 
30
283
  jsi::Array presentationArray(
@@ -33,18 +286,9 @@ jsi::Array presentationArray(
33
286
  bool includeHandled = false,
34
287
  bool handled = true) {
35
288
  const size_t offset = includeHandled ? 1 : 0;
36
- jsi::Array result(runtime, offset + 7);
37
- // JS checks `values[0] !== 1`, so the handled flag must be a number: a jsi
38
- // bool would make every comparison fail and leave the driver stuck in
39
- // native ownership after cancelAnimation.
289
+ jsi::Array result(runtime, offset + kPresentationStride);
40
290
  if (includeHandled) result.setValueAtIndex(runtime, 0, handled ? 1.0 : 0.0);
41
- result.setValueAtIndex(runtime, offset, presentation.clip.x);
42
- result.setValueAtIndex(runtime, offset + 1, presentation.clip.y);
43
- result.setValueAtIndex(runtime, offset + 2, presentation.clip.width);
44
- result.setValueAtIndex(runtime, offset + 3, presentation.clip.height);
45
- result.setValueAtIndex(runtime, offset + 4, presentation.clip.radius);
46
- result.setValueAtIndex(runtime, offset + 5, presentation.contentTranslateX);
47
- result.setValueAtIndex(runtime, offset + 6, presentation.contentTranslateY);
291
+ writePresentation(runtime, result, offset, presentation);
48
292
  return result;
49
293
  }
50
294
 
@@ -55,210 +299,320 @@ SmoothClipTurboModule::SmoothClipTurboModule(
55
299
  : NativeSmoothClipModuleCxxSpec(std::move(jsInvoker)) {
56
300
  smoothclip::setCompletionCallback(
57
301
  this,
58
- [this](uint64_t driverId, int32_t animationId, bool finished) {
302
+ [this](
303
+ uint64_t driverId,
304
+ int32_t animationId,
305
+ int32_t completionTag,
306
+ bool finished) {
59
307
  emitOnClipAnimationComplete(SmoothClipAnimationCompletion{
60
- static_cast<double>(driverId), animationId, finished});
308
+ static_cast<double>(driverId), animationId, completionTag, finished});
309
+ });
310
+ smoothclip::setGroupCompletionCallback(
311
+ this,
312
+ [this](
313
+ uint64_t controllerId,
314
+ int32_t groupId,
315
+ int32_t completionTag,
316
+ bool finished,
317
+ std::vector<smoothclip::DriverSnapshot> snapshots) {
318
+ emitOnClipGroupAnimationComplete(
319
+ SmoothClipGroupAnimationCompletion{
320
+ static_cast<double>(controllerId),
321
+ groupId,
322
+ completionTag,
323
+ finished,
324
+ snapshotValues(snapshots),
325
+ });
61
326
  });
62
327
  }
63
328
 
64
329
  SmoothClipTurboModule::~SmoothClipTurboModule() {
65
330
  smoothclip::clearCompletionCallback(this);
331
+ smoothclip::clearGroupCompletionCallback(this);
332
+ }
333
+
334
+ bool SmoothClipTurboModule::supportsAutonomousComplexPathAnimation(
335
+ jsi::Runtime &) {
336
+ return false;
337
+ }
338
+
339
+ jsi::Array SmoothClipTurboModule::beginGroupInteraction(
340
+ jsi::Runtime &runtime,
341
+ jsi::Array driverIds) {
342
+ std::vector<uint64_t> parsed;
343
+ if (!driverIdsAt(runtime, driverIds, parsed)) {
344
+ return jsi::Array(runtime, 0);
345
+ }
346
+ return snapshotArray(
347
+ runtime, smoothclip::beginGroupInteraction(parsed));
348
+ }
349
+
350
+ jsi::Array SmoothClipTurboModule::snapshotGroup(
351
+ jsi::Runtime &runtime,
352
+ jsi::Array driverIds) {
353
+ std::vector<uint64_t> parsed;
354
+ if (!driverIdsAt(runtime, driverIds, parsed)) {
355
+ return jsi::Array(runtime, 0);
356
+ }
357
+ return snapshotArray(runtime, smoothclip::snapshotGroup(parsed));
358
+ }
359
+
360
+ bool SmoothClipTurboModule::setClipPresentationBatch(
361
+ jsi::Runtime &runtime,
362
+ jsi::Array entries) {
363
+ constexpr size_t stride = kSnapshotStride;
364
+ const size_t count = entries.size(runtime);
365
+ if (count % stride != 0) return false;
366
+ std::vector<smoothclip::BatchEntry> parsed;
367
+ parsed.reserve(count / stride);
368
+ for (size_t offset = 0; offset < count; offset += stride) {
369
+ double driverId = 0;
370
+ smoothclip::Presentation presentation;
371
+ if (!numberAt(runtime, entries, offset, driverId) ||
372
+ !validDriverId(driverId) ||
373
+ !presentationAt(runtime, entries, offset + 1, presentation)) {
374
+ return false;
375
+ }
376
+ parsed.push_back(
377
+ {static_cast<uint64_t>(driverId), presentation});
378
+ }
379
+ return smoothclip::setPresentationBatch(parsed);
380
+ }
381
+
382
+ int32_t SmoothClipTurboModule::animateTimingGroup(
383
+ jsi::Runtime &runtime,
384
+ double controllerId,
385
+ jsi::Array entries,
386
+ double durationMs,
387
+ double controlPoint1X,
388
+ double controlPoint1Y,
389
+ double controlPoint2X,
390
+ double controlPoint2Y,
391
+ int32_t reduceMotion,
392
+ int32_t completionTag,
393
+ double startTimestamp) {
394
+ (void)startTimestamp;
395
+ std::vector<smoothclip::GroupMotionEntry> parsed;
396
+ if (!validDriverId(controllerId) ||
397
+ !fixedGroupEntriesAt(runtime, entries, parsed) ||
398
+ !std::isfinite(durationMs) || !std::isfinite(controlPoint1X) ||
399
+ !std::isfinite(controlPoint1Y) || !std::isfinite(controlPoint2X) ||
400
+ !std::isfinite(controlPoint2Y)) {
401
+ return 0;
402
+ }
403
+ return smoothclip::animateTimingGroup(
404
+ static_cast<uint64_t>(controllerId),
405
+ std::move(parsed),
406
+ {durationMs,
407
+ controlPoint1X,
408
+ controlPoint1Y,
409
+ controlPoint2X,
410
+ controlPoint2Y,
411
+ reduceMotion},
412
+ completionTag);
413
+ }
414
+
415
+ int32_t SmoothClipTurboModule::animateSpringGroup(
416
+ jsi::Runtime &runtime,
417
+ double controllerId,
418
+ jsi::Array entries,
419
+ double mass,
420
+ double stiffness,
421
+ double damping,
422
+ double velocity,
423
+ double energyThreshold,
424
+ int32_t reduceMotion,
425
+ int32_t completionTag,
426
+ double startTimestamp) {
427
+ (void)startTimestamp;
428
+ std::vector<smoothclip::GroupMotionEntry> parsed;
429
+ if (!validDriverId(controllerId) ||
430
+ !fixedGroupEntriesAt(runtime, entries, parsed) ||
431
+ !std::isfinite(mass) || !std::isfinite(stiffness) ||
432
+ !std::isfinite(damping) || !std::isfinite(velocity) ||
433
+ !std::isfinite(energyThreshold) || mass <= 0 || stiffness <= 0 ||
434
+ damping < 0 || energyThreshold <= 0) {
435
+ return 0;
436
+ }
437
+ return smoothclip::animateSpringGroup(
438
+ static_cast<uint64_t>(controllerId),
439
+ std::move(parsed),
440
+ {mass,
441
+ stiffness,
442
+ damping,
443
+ velocity,
444
+ false,
445
+ reduceMotion,
446
+ energyThreshold},
447
+ completionTag);
448
+ }
449
+
450
+ jsi::Array SmoothClipTurboModule::cancelAnimationGroup(
451
+ jsi::Runtime &runtime,
452
+ int32_t groupId,
453
+ int32_t behavior) {
454
+ if (groupId <= 0 ||
455
+ (behavior != static_cast<int32_t>(
456
+ smoothclip::GroupCancelBehavior::Freeze) &&
457
+ behavior != static_cast<int32_t>(
458
+ smoothclip::GroupCancelBehavior::Finish))) {
459
+ return jsi::Array(runtime, 0);
460
+ }
461
+ return snapshotArray(
462
+ runtime,
463
+ smoothclip::cancelAnimationGroup(
464
+ groupId,
465
+ static_cast<smoothclip::GroupCancelBehavior>(behavior)));
66
466
  }
67
467
 
68
468
  void SmoothClipTurboModule::setClipPresentation(
469
+ jsi::Runtime &runtime,
470
+ double driverId,
471
+ jsi::Array values,
472
+ bool takeOwnership,
473
+ bool overridePendingAnimation) {
474
+ smoothclip::Presentation presentation{};
475
+ if (values.size(runtime) == kPresentationStride &&
476
+ validDriverId(driverId) &&
477
+ presentationAt(runtime, values, 0, presentation)) {
478
+ smoothclip::setPresentation(
479
+ static_cast<uint64_t>(driverId), presentation, takeOwnership,
480
+ overridePendingAnimation);
481
+ }
482
+ }
483
+
484
+ void SmoothClipTurboModule::setClipFrameScalars(
69
485
  jsi::Runtime &,
70
486
  double driverId,
71
487
  double x,
72
488
  double y,
73
489
  double width,
74
490
  double height,
75
- double radius,
491
+ double topLeftRadius,
492
+ double topRightRadius,
493
+ double bottomRightRadius,
494
+ double bottomLeftRadius,
495
+ int32_t curveCode,
76
496
  double contentTranslateX,
77
497
  double contentTranslateY,
78
- bool takeOwnership,
79
- bool overridePendingAnimation) {
80
- const smoothclip::Presentation presentation{
81
- {x, y, width, height, radius}, contentTranslateX, contentTranslateY};
82
- if (validDriverId(driverId) && finitePresentation(presentation)) {
83
- smoothclip::setPresentation(
84
- static_cast<uint64_t>(driverId), presentation, takeOwnership,
85
- overridePendingAnimation);
86
- }
498
+ double contentScale,
499
+ bool shadowEnabled,
500
+ double shadowRed,
501
+ double shadowGreen,
502
+ double shadowBlue,
503
+ double shadowAlpha,
504
+ double shadowOffsetX,
505
+ double shadowOffsetY,
506
+ double shadowBlurRadius,
507
+ double shadowSpreadDistance) {
508
+ const smoothclip::Presentation presentation = makePresentation(
509
+ x, y, width, height, topLeftRadius, topRightRadius,
510
+ bottomRightRadius, bottomLeftRadius, curveCode,
511
+ contentTranslateX, contentTranslateY, contentScale,
512
+ shadowEnabled, shadowRed, shadowGreen, shadowBlue, shadowAlpha,
513
+ shadowOffsetX, shadowOffsetY, shadowBlurRadius, shadowSpreadDistance);
514
+ if (!validDriverId(driverId) || !finitePresentation(presentation)) return;
515
+ smoothclip::setPresentation(
516
+ static_cast<uint64_t>(driverId), presentation, true, false, true);
87
517
  }
88
518
 
89
519
  jsi::Array SmoothClipTurboModule::beginInteraction(
90
520
  jsi::Runtime &runtime,
91
521
  double driverId) {
92
522
  if (!validDriverId(driverId)) {
93
- return presentationArray(runtime, {{0, 0, 0, 0, 0}, 0, 0});
523
+ return presentationArray(
524
+ runtime, makePresentation(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1));
94
525
  }
95
526
  return presentationArray(
96
527
  runtime,
97
528
  smoothclip::beginInteraction(static_cast<uint64_t>(driverId)));
98
529
  }
99
530
 
531
+ jsi::Array SmoothClipTurboModule::snapshotCurrent(
532
+ jsi::Runtime &runtime,
533
+ double driverId) {
534
+ if (!validDriverId(driverId)) {
535
+ return presentationArray(
536
+ runtime, makePresentation(NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN,
537
+ 0, NAN, NAN, NAN));
538
+ }
539
+ return presentationArray(
540
+ runtime,
541
+ smoothclip::snapshotCurrent(static_cast<uint64_t>(driverId)));
542
+ }
543
+
100
544
  int32_t SmoothClipTurboModule::animateTiming(
101
- jsi::Runtime &,
545
+ jsi::Runtime &runtime,
102
546
  double driverId,
103
- bool hasInteractiveStart,
104
- double startX,
105
- double startY,
106
- double startWidth,
107
- double startHeight,
108
- double startRadius,
109
- double startContentTranslateX,
110
- double startContentTranslateY,
111
- double x,
112
- double y,
113
- double width,
114
- double height,
115
- double radius,
116
- double contentTranslateX,
117
- double contentTranslateY,
547
+ jsi::Array start,
548
+ jsi::Array target,
118
549
  double durationMs,
119
550
  double controlPoint1X,
120
551
  double controlPoint1Y,
121
552
  double controlPoint2X,
122
553
  double controlPoint2Y,
123
- int32_t reduceMotion) {
124
- const smoothclip::Presentation startPresentation{
125
- {startX, startY, startWidth, startHeight, startRadius},
126
- startContentTranslateX,
127
- startContentTranslateY};
128
- const smoothclip::Presentation presentation{
129
- {x, y, width, height, radius}, contentTranslateX, contentTranslateY};
554
+ int32_t reduceMotion,
555
+ int32_t completionTag) {
556
+ const bool hasInteractiveStart = start.size(runtime) != 0;
557
+ smoothclip::Presentation startPresentation{};
558
+ smoothclip::Presentation presentation{};
130
559
  const smoothclip::TimingAnimation animation{
131
- durationMs,
132
- controlPoint1X,
133
- controlPoint1Y,
134
- controlPoint2X,
135
- controlPoint2Y,
136
- reduceMotion};
560
+ durationMs, controlPoint1X, controlPoint1Y,
561
+ controlPoint2X, controlPoint2Y, reduceMotion};
137
562
  if (!validDriverId(driverId) ||
138
- !finitePresentation(startPresentation) ||
139
- !finitePresentation(presentation) ||
563
+ (hasInteractiveStart &&
564
+ (start.size(runtime) != kPresentationStride ||
565
+ !presentationAt(runtime, start, 0, startPresentation))) ||
566
+ target.size(runtime) != kPresentationStride ||
567
+ !presentationAt(runtime, target, 0, presentation) ||
140
568
  !std::isfinite(durationMs) || !std::isfinite(controlPoint1X) ||
141
569
  !std::isfinite(controlPoint1Y) || !std::isfinite(controlPoint2X) ||
142
- !std::isfinite(controlPoint2Y)) return 0;
143
-
570
+ !std::isfinite(controlPoint2Y)) {
571
+ return 0;
572
+ }
144
573
  return smoothclip::animateTiming(
145
574
  static_cast<uint64_t>(driverId),
146
575
  {hasInteractiveStart, startPresentation},
147
576
  presentation,
148
- animation);
577
+ animation,
578
+ completionTag);
149
579
  }
150
580
 
151
581
  int32_t SmoothClipTurboModule::animateSpring(
152
- jsi::Runtime &,
582
+ jsi::Runtime &runtime,
153
583
  double driverId,
154
- bool hasInteractiveStart,
155
- double startX,
156
- double startY,
157
- double startWidth,
158
- double startHeight,
159
- double startRadius,
160
- double startContentTranslateX,
161
- double startContentTranslateY,
162
- double x,
163
- double y,
164
- double width,
165
- double height,
166
- double radius,
167
- double contentTranslateX,
168
- double contentTranslateY,
584
+ jsi::Array start,
585
+ jsi::Array target,
169
586
  double mass,
170
587
  double stiffness,
171
588
  double damping,
172
589
  double initialVelocity,
173
590
  bool inheritVelocity,
174
- int32_t reduceMotion) {
175
- const smoothclip::Presentation startPresentation{
176
- {startX, startY, startWidth, startHeight, startRadius},
177
- startContentTranslateX,
178
- startContentTranslateY};
179
- const smoothclip::Presentation presentation{
180
- {x, y, width, height, radius}, contentTranslateX, contentTranslateY};
591
+ int32_t reduceMotion,
592
+ int32_t completionTag) {
593
+ const bool hasInteractiveStart = start.size(runtime) != 0;
594
+ smoothclip::Presentation startPresentation{};
595
+ smoothclip::Presentation presentation{};
181
596
  const smoothclip::SpringAnimation animation{
182
- mass,
183
- stiffness,
184
- damping,
185
- initialVelocity,
186
- inheritVelocity,
187
- reduceMotion};
597
+ mass, stiffness, damping, initialVelocity,
598
+ inheritVelocity, reduceMotion};
188
599
  if (!validDriverId(driverId) ||
189
- !finitePresentation(startPresentation) ||
190
- !finitePresentation(presentation) ||
600
+ (hasInteractiveStart &&
601
+ (start.size(runtime) != kPresentationStride ||
602
+ !presentationAt(runtime, start, 0, startPresentation))) ||
603
+ target.size(runtime) != kPresentationStride ||
604
+ !presentationAt(runtime, target, 0, presentation) ||
191
605
  !std::isfinite(mass) || !std::isfinite(stiffness) ||
192
606
  !std::isfinite(damping) || !std::isfinite(initialVelocity) ||
193
- mass <= 0 || stiffness <= 0 || damping < 0) return 0;
194
-
195
- return smoothclip::animateSpring(
196
- static_cast<uint64_t>(driverId),
197
- {hasInteractiveStart, startPresentation},
198
- presentation,
199
- animation);
200
- }
201
-
202
- int32_t SmoothClipTurboModule::animateKeyframes(
203
- jsi::Runtime &runtime,
204
- double driverId,
205
- bool hasInteractiveStart,
206
- double startX,
207
- double startY,
208
- double startWidth,
209
- double startHeight,
210
- double startRadius,
211
- double startContentTranslateX,
212
- double startContentTranslateY,
213
- double x,
214
- double y,
215
- double width,
216
- double height,
217
- double radius,
218
- double contentTranslateX,
219
- double contentTranslateY,
220
- double durationMs,
221
- jsi::Array frames,
222
- int32_t reduceMotion) {
223
- const smoothclip::Presentation startPresentation{
224
- {startX, startY, startWidth, startHeight, startRadius},
225
- startContentTranslateX,
226
- startContentTranslateY};
227
- const smoothclip::Presentation presentation{
228
- {x, y, width, height, radius}, contentTranslateX, contentTranslateY};
229
- if (!validDriverId(driverId) ||
230
- !finitePresentation(startPresentation) ||
231
- !finitePresentation(presentation) || !std::isfinite(durationMs) ||
232
- frames.size(runtime) < 16 || frames.size(runtime) % 8 != 0) {
607
+ mass <= 0 || stiffness <= 0 || damping < 0) {
233
608
  return 0;
234
609
  }
235
-
236
- std::vector<smoothclip::Keyframe> keyframes;
237
- keyframes.reserve(frames.size(runtime) / 8);
238
- double previousOffset = -1;
239
- for (size_t index = 0; index < frames.size(runtime); index += 8) {
240
- const double offset = frames.getValueAtIndex(runtime, index).asNumber();
241
- smoothclip::Presentation frame{
242
- {frames.getValueAtIndex(runtime, index + 1).asNumber(),
243
- frames.getValueAtIndex(runtime, index + 2).asNumber(),
244
- frames.getValueAtIndex(runtime, index + 3).asNumber(),
245
- frames.getValueAtIndex(runtime, index + 4).asNumber(),
246
- frames.getValueAtIndex(runtime, index + 5).asNumber()},
247
- frames.getValueAtIndex(runtime, index + 6).asNumber(),
248
- frames.getValueAtIndex(runtime, index + 7).asNumber()};
249
- if (!std::isfinite(offset) || offset < 0 || offset > 1 ||
250
- offset <= previousOffset || !finitePresentation(frame)) return 0;
251
- previousOffset = offset;
252
- keyframes.push_back({offset, frame});
253
- }
254
- if (keyframes.front().offset != 0 || keyframes.back().offset != 1) return 0;
255
- return smoothclip::animateKeyframes(
610
+ return smoothclip::animateSpring(
256
611
  static_cast<uint64_t>(driverId),
257
612
  {hasInteractiveStart, startPresentation},
258
613
  presentation,
259
- durationMs,
260
- std::move(keyframes),
261
- reduceMotion);
614
+ animation,
615
+ completionTag);
262
616
  }
263
617
 
264
618
  int32_t SmoothClipTurboModule::rejectAnimation(
@@ -275,7 +629,10 @@ jsi::Array SmoothClipTurboModule::cancelAnimation(
275
629
  int32_t behavior) {
276
630
  if (!validDriverId(driverId)) {
277
631
  return presentationArray(
278
- runtime, {{0, 0, 0, 0, 0}, 0, 0}, true, false);
632
+ runtime,
633
+ makePresentation(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
634
+ true,
635
+ false);
279
636
  }
280
637
  const smoothclip::CancelResult result = smoothclip::cancelAnimation(
281
638
  static_cast<uint64_t>(driverId), animationId, behavior == 1);