react-native-smooth-clip-view 0.1.0 → 0.2.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.
- package/README.md +164 -43
- package/SmoothClipView.podspec +8 -2
- package/android/CMakeLists.txt +39 -0
- package/android/build.gradle +69 -2
- package/android/proguard-rules.pro +6 -0
- package/android/src/main/cpp/SmoothClipAndroid.h +59 -0
- package/android/src/main/cpp/SmoothClipBindings.cpp +428 -0
- package/android/src/main/cpp/SmoothClipRegistry.cpp +913 -0
- package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +25 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +55 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +128 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +164 -30
- package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +107 -10
- package/android/src/main/java/com/smoothclipview/SmoothClipViewPackage.kt +18 -2
- package/cpp/SmoothClipRegistry.h +93 -0
- package/cpp/SmoothClipSharedGeometry.h +50 -0
- package/ios/SmoothClipModuleProvider.h +9 -0
- package/ios/SmoothClipModuleProvider.mm +16 -0
- package/ios/SmoothClipRegistry.mm +717 -0
- package/ios/SmoothClipTurboModule.cpp +290 -0
- package/ios/SmoothClipTurboModule.h +132 -0
- package/ios/SmoothClipView.mm +976 -85
- package/ios/SmoothClipViewRegistry.h +27 -0
- package/lib/module/NativeSmoothClipModule.js +5 -0
- package/lib/module/NativeSmoothClipModule.js.map +1 -0
- package/lib/module/SmoothClipView.android.js +4 -0
- package/lib/module/SmoothClipView.android.js.map +1 -0
- package/lib/module/SmoothClipView.ios.js +34 -0
- package/lib/module/SmoothClipView.ios.js.map +1 -0
- package/lib/module/SmoothClipView.js +26 -12
- package/lib/module/SmoothClipView.js.map +1 -1
- package/lib/module/SmoothClipView.web.js +28 -12
- package/lib/module/SmoothClipView.web.js.map +1 -1
- package/lib/module/SmoothClipViewNativeComponent.ts +14 -1
- package/lib/module/driverState.js +102 -0
- package/lib/module/driverState.js.map +1 -0
- package/lib/module/driverTypes.js +4 -0
- package/lib/module/driverTypes.js.map +1 -0
- package/lib/module/drivers.android.js +4 -0
- package/lib/module/drivers.android.js.map +1 -0
- package/lib/module/drivers.ios.js +380 -0
- package/lib/module/drivers.ios.js.map +1 -0
- package/lib/module/drivers.js +276 -0
- package/lib/module/drivers.js.map +1 -0
- package/lib/module/geometry.js +19 -0
- package/lib/module/geometry.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +2 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/nativeCompletion.js +21 -0
- package/lib/module/nativeCompletion.js.map +1 -0
- package/lib/module/reactRequests.js +50 -0
- package/lib/module/reactRequests.js.map +1 -0
- package/lib/module/smoothClipNative.android.js +15 -0
- package/lib/module/smoothClipNative.android.js.map +1 -0
- package/lib/module/smoothClipNative.js +8 -0
- package/lib/module/smoothClipNative.js.map +1 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts +19 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.android.d.ts +3 -0
- package/lib/typescript/src/SmoothClipView.android.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.d.ts +5 -6
- package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.ios.d.ts +9 -0
- package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.web.d.ts +5 -7
- package/lib/typescript/src/SmoothClipView.web.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +4 -0
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/driverState.d.ts +31 -0
- package/lib/typescript/src/driverState.d.ts.map +1 -0
- package/lib/typescript/src/driverTypes.d.ts +61 -0
- package/lib/typescript/src/driverTypes.d.ts.map +1 -0
- package/lib/typescript/src/drivers.android.d.ts +3 -0
- package/lib/typescript/src/drivers.android.d.ts.map +1 -0
- package/lib/typescript/src/drivers.d.ts +5 -0
- package/lib/typescript/src/drivers.d.ts.map +1 -0
- package/lib/typescript/src/drivers.ios.d.ts +5 -0
- package/lib/typescript/src/drivers.ios.d.ts.map +1 -0
- package/lib/typescript/src/geometry.d.ts +8 -0
- package/lib/typescript/src/geometry.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +4 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/nativeCompletion.d.ts +7 -0
- package/lib/typescript/src/nativeCompletion.d.ts.map +1 -0
- package/lib/typescript/src/reactRequests.d.ts +7 -0
- package/lib/typescript/src/reactRequests.d.ts.map +1 -0
- package/lib/typescript/src/smoothClipNative.android.d.ts +4 -0
- package/lib/typescript/src/smoothClipNative.android.d.ts.map +1 -0
- package/lib/typescript/src/smoothClipNative.d.ts +3 -0
- package/lib/typescript/src/smoothClipNative.d.ts.map +1 -0
- package/package.json +12 -7
- package/src/NativeSmoothClipModule.ts +104 -0
- package/src/SmoothClipView.android.tsx +2 -0
- package/src/SmoothClipView.ios.tsx +36 -0
- package/src/SmoothClipView.tsx +31 -27
- package/src/SmoothClipView.web.tsx +26 -22
- package/src/SmoothClipViewNativeComponent.ts +14 -1
- package/src/driverState.ts +150 -0
- package/src/driverTypes.ts +91 -0
- package/src/drivers.android.ts +6 -0
- package/src/drivers.ios.ts +665 -0
- package/src/drivers.ts +416 -0
- package/src/geometry.ts +39 -0
- package/src/index.ts +19 -1
- package/src/index.web.ts +19 -1
- package/src/nativeCompletion.ts +37 -0
- package/src/reactRequests.ts +64 -0
- package/src/smoothClipNative.android.ts +20 -0
- package/src/smoothClipNative.ts +5 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#include "SmoothClipAndroid.h"
|
|
2
|
+
|
|
3
|
+
#include <ReactCommon/BindingsInstallerHolder.h>
|
|
4
|
+
#include <ReactCommon/CallInvoker.h>
|
|
5
|
+
#include <fbjni/fbjni.h>
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
|
|
8
|
+
#include <cmath>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <unordered_map>
|
|
11
|
+
#include <utility>
|
|
12
|
+
#include <vector>
|
|
13
|
+
|
|
14
|
+
using namespace facebook;
|
|
15
|
+
using facebook::jsi::Array;
|
|
16
|
+
using facebook::jsi::Function;
|
|
17
|
+
using facebook::jsi::Object;
|
|
18
|
+
using facebook::jsi::PropNameID;
|
|
19
|
+
using facebook::jsi::Runtime;
|
|
20
|
+
using facebook::jsi::Value;
|
|
21
|
+
using facebook::react::BindingsInstallerHolder;
|
|
22
|
+
using facebook::react::CallInvoker;
|
|
23
|
+
|
|
24
|
+
namespace smoothclip {
|
|
25
|
+
namespace {
|
|
26
|
+
|
|
27
|
+
constexpr double kMaxSafeJavaScriptInteger = 9007199254740991.0;
|
|
28
|
+
|
|
29
|
+
bool validDriverId(double value) {
|
|
30
|
+
return std::isfinite(value) && value > 0 &&
|
|
31
|
+
value <= kMaxSafeJavaScriptInteger && std::floor(value) == value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
bool finitePresentation(const Presentation &presentation) {
|
|
35
|
+
return std::isfinite(presentation.clip.x) &&
|
|
36
|
+
std::isfinite(presentation.clip.y) &&
|
|
37
|
+
std::isfinite(presentation.clip.width) &&
|
|
38
|
+
std::isfinite(presentation.clip.height) &&
|
|
39
|
+
std::isfinite(presentation.clip.radius) &&
|
|
40
|
+
std::isfinite(presentation.contentTranslateX) &&
|
|
41
|
+
std::isfinite(presentation.contentTranslateY);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bool boolArg(const Value *args, size_t count, size_t index) {
|
|
45
|
+
return index < count && args[index].isBool() && args[index].getBool();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Presentation presentationFromArgs(const Value *args, size_t offset) {
|
|
49
|
+
return Presentation{
|
|
50
|
+
{args[offset].asNumber(),
|
|
51
|
+
args[offset + 1].asNumber(),
|
|
52
|
+
args[offset + 2].asNumber(),
|
|
53
|
+
args[offset + 3].asNumber(),
|
|
54
|
+
args[offset + 4].asNumber()},
|
|
55
|
+
args[offset + 5].asNumber(),
|
|
56
|
+
args[offset + 6].asNumber()};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Array presentationArray(Runtime &runtime, const Presentation &presentation) {
|
|
60
|
+
Array result(runtime, 7);
|
|
61
|
+
result.setValueAtIndex(runtime, 0, presentation.clip.x);
|
|
62
|
+
result.setValueAtIndex(runtime, 1, presentation.clip.y);
|
|
63
|
+
result.setValueAtIndex(runtime, 2, presentation.clip.width);
|
|
64
|
+
result.setValueAtIndex(runtime, 3, presentation.clip.height);
|
|
65
|
+
result.setValueAtIndex(runtime, 4, presentation.clip.radius);
|
|
66
|
+
result.setValueAtIndex(runtime, 5, presentation.contentTranslateX);
|
|
67
|
+
result.setValueAtIndex(runtime, 6, presentation.contentTranslateY);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Array cancelResultArray(
|
|
72
|
+
Runtime &runtime,
|
|
73
|
+
bool handled,
|
|
74
|
+
const Presentation &presentation) {
|
|
75
|
+
Array result(runtime, 8);
|
|
76
|
+
// JS checks `values[0] !== 1`, so the handled flag must be a number.
|
|
77
|
+
result.setValueAtIndex(runtime, 0, handled ? 1.0 : 0.0);
|
|
78
|
+
result.setValueAtIndex(runtime, 1, presentation.clip.x);
|
|
79
|
+
result.setValueAtIndex(runtime, 2, presentation.clip.y);
|
|
80
|
+
result.setValueAtIndex(runtime, 3, presentation.clip.width);
|
|
81
|
+
result.setValueAtIndex(runtime, 4, presentation.clip.height);
|
|
82
|
+
result.setValueAtIndex(runtime, 5, presentation.clip.radius);
|
|
83
|
+
result.setValueAtIndex(runtime, 6, presentation.contentTranslateX);
|
|
84
|
+
result.setValueAtIndex(runtime, 7, presentation.contentTranslateY);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
struct BindingsState {
|
|
89
|
+
Runtime *runtime = nullptr;
|
|
90
|
+
std::shared_ptr<CallInvoker> callInvoker;
|
|
91
|
+
std::unordered_map<int32_t, std::shared_ptr<Function>> listeners;
|
|
92
|
+
int32_t nextListenerId = 0;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
std::shared_ptr<BindingsState> &bindingsState() {
|
|
96
|
+
static std::shared_ptr<BindingsState> state = std::make_shared<BindingsState>();
|
|
97
|
+
return state;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
void setHostFunction(
|
|
101
|
+
Runtime &runtime,
|
|
102
|
+
Object &target,
|
|
103
|
+
const char *name,
|
|
104
|
+
unsigned int paramCount,
|
|
105
|
+
jsi::HostFunctionType &&function) {
|
|
106
|
+
target.setProperty(
|
|
107
|
+
runtime,
|
|
108
|
+
name,
|
|
109
|
+
Function::createFromHostFunction(
|
|
110
|
+
runtime,
|
|
111
|
+
PropNameID::forAscii(runtime, name),
|
|
112
|
+
paramCount,
|
|
113
|
+
std::move(function)));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
} // namespace
|
|
117
|
+
|
|
118
|
+
void installBindings(
|
|
119
|
+
Runtime &runtime,
|
|
120
|
+
const std::shared_ptr<CallInvoker> &callInvoker) {
|
|
121
|
+
auto state = bindingsState();
|
|
122
|
+
// A reinstall means a new runtime (reload / new host). Listener functions
|
|
123
|
+
// created on the previous runtime must never be called with — or destroyed
|
|
124
|
+
// against — the new one; the TurboModule invalidate hook releases them
|
|
125
|
+
// while their runtime is still alive, and this is the safety net.
|
|
126
|
+
state->listeners.clear();
|
|
127
|
+
state->runtime = &runtime;
|
|
128
|
+
state->callInvoker = callInvoker;
|
|
129
|
+
|
|
130
|
+
setCompletionCallback(
|
|
131
|
+
state.get(),
|
|
132
|
+
[state](uint64_t driverId, int32_t animationId, bool finished) {
|
|
133
|
+
auto invoker = state->callInvoker;
|
|
134
|
+
if (!invoker) return;
|
|
135
|
+
invoker->invokeAsync([state, driverId, animationId, finished]() {
|
|
136
|
+
if (state->runtime == nullptr) return;
|
|
137
|
+
Runtime &rt = *state->runtime;
|
|
138
|
+
std::vector<std::shared_ptr<Function>> snapshot;
|
|
139
|
+
snapshot.reserve(state->listeners.size());
|
|
140
|
+
for (const auto &entry : state->listeners) {
|
|
141
|
+
snapshot.push_back(entry.second);
|
|
142
|
+
}
|
|
143
|
+
for (const auto &listener : snapshot) {
|
|
144
|
+
Object result(rt);
|
|
145
|
+
result.setProperty(rt, "driverId", static_cast<double>(driverId));
|
|
146
|
+
result.setProperty(rt, "animationId", animationId);
|
|
147
|
+
result.setProperty(rt, "finished", finished);
|
|
148
|
+
listener->call(rt, std::move(result));
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
Object bindings(runtime);
|
|
154
|
+
|
|
155
|
+
setHostFunction(
|
|
156
|
+
runtime, bindings, "setClipPresentation", 9,
|
|
157
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
158
|
+
if (count < 9) return Value::undefined();
|
|
159
|
+
const double driverId = args[0].asNumber();
|
|
160
|
+
const Presentation presentation = presentationFromArgs(args, 1);
|
|
161
|
+
const bool takeOwnership = boolArg(args, count, 8);
|
|
162
|
+
if (validDriverId(driverId) && finitePresentation(presentation)) {
|
|
163
|
+
setPresentation(
|
|
164
|
+
static_cast<uint64_t>(driverId), presentation, takeOwnership);
|
|
165
|
+
}
|
|
166
|
+
return Value::undefined();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
setHostFunction(
|
|
170
|
+
runtime, bindings, "beginInteraction", 1,
|
|
171
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
172
|
+
if (count < 1 || !validDriverId(args[0].asNumber())) {
|
|
173
|
+
return presentationArray(rt, {{0, 0, 0, 0, 0}, 0, 0});
|
|
174
|
+
}
|
|
175
|
+
return presentationArray(
|
|
176
|
+
rt, beginInteraction(static_cast<uint64_t>(args[0].asNumber())));
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
setHostFunction(
|
|
180
|
+
runtime, bindings, "animateTiming", 22,
|
|
181
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
182
|
+
if (count < 22) return Value(0);
|
|
183
|
+
const double driverId = args[0].asNumber();
|
|
184
|
+
const Presentation start = presentationFromArgs(args, 2);
|
|
185
|
+
const Presentation target = presentationFromArgs(args, 9);
|
|
186
|
+
const TimingAnimation animation{
|
|
187
|
+
args[16].asNumber(), args[17].asNumber(), args[18].asNumber(),
|
|
188
|
+
args[19].asNumber(), args[20].asNumber(),
|
|
189
|
+
static_cast<int32_t>(args[21].asNumber())};
|
|
190
|
+
if (!validDriverId(driverId) || !finitePresentation(start) ||
|
|
191
|
+
!finitePresentation(target) ||
|
|
192
|
+
!std::isfinite(animation.durationMs)) {
|
|
193
|
+
return Value(0);
|
|
194
|
+
}
|
|
195
|
+
return Value(animateTiming(
|
|
196
|
+
static_cast<uint64_t>(driverId),
|
|
197
|
+
{boolArg(args, count, 1), start},
|
|
198
|
+
target,
|
|
199
|
+
animation));
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
setHostFunction(
|
|
203
|
+
runtime, bindings, "animateSpring", 22,
|
|
204
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
205
|
+
if (count < 22) return Value(0);
|
|
206
|
+
const double driverId = args[0].asNumber();
|
|
207
|
+
const Presentation start = presentationFromArgs(args, 2);
|
|
208
|
+
const Presentation target = presentationFromArgs(args, 9);
|
|
209
|
+
const SpringAnimation animation{
|
|
210
|
+
args[16].asNumber(), args[17].asNumber(), args[18].asNumber(),
|
|
211
|
+
args[19].asNumber(), boolArg(args, count, 20),
|
|
212
|
+
static_cast<int32_t>(args[21].asNumber())};
|
|
213
|
+
if (!validDriverId(driverId) || !finitePresentation(start) ||
|
|
214
|
+
!finitePresentation(target) || !std::isfinite(animation.mass) ||
|
|
215
|
+
!std::isfinite(animation.stiffness) ||
|
|
216
|
+
!std::isfinite(animation.damping) ||
|
|
217
|
+
!std::isfinite(animation.initialVelocity) ||
|
|
218
|
+
animation.mass <= 0 || animation.stiffness <= 0 ||
|
|
219
|
+
animation.damping < 0) {
|
|
220
|
+
return Value(0);
|
|
221
|
+
}
|
|
222
|
+
return Value(animateSpring(
|
|
223
|
+
static_cast<uint64_t>(driverId),
|
|
224
|
+
{boolArg(args, count, 1), start},
|
|
225
|
+
target,
|
|
226
|
+
animation));
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
setHostFunction(
|
|
230
|
+
runtime, bindings, "animateKeyframes", 19,
|
|
231
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
232
|
+
if (count < 19 || !args[17].isObject() ||
|
|
233
|
+
!args[17].getObject(rt).isArray(rt)) {
|
|
234
|
+
return Value(0);
|
|
235
|
+
}
|
|
236
|
+
const double driverId = args[0].asNumber();
|
|
237
|
+
const Presentation start = presentationFromArgs(args, 2);
|
|
238
|
+
const Presentation target = presentationFromArgs(args, 9);
|
|
239
|
+
const double durationMs = args[16].asNumber();
|
|
240
|
+
const int32_t reduceMotion = static_cast<int32_t>(args[18].asNumber());
|
|
241
|
+
Array frames = args[17].getObject(rt).getArray(rt);
|
|
242
|
+
const size_t length = frames.size(rt);
|
|
243
|
+
if (!validDriverId(driverId) || !finitePresentation(start) ||
|
|
244
|
+
!finitePresentation(target) || !std::isfinite(durationMs) ||
|
|
245
|
+
length < 16 || length % 8 != 0) {
|
|
246
|
+
return Value(0);
|
|
247
|
+
}
|
|
248
|
+
std::vector<Keyframe> keyframes;
|
|
249
|
+
keyframes.reserve(length / 8);
|
|
250
|
+
double previousOffset = -1;
|
|
251
|
+
for (size_t index = 0; index < length; index += 8) {
|
|
252
|
+
const double offset = frames.getValueAtIndex(rt, index).asNumber();
|
|
253
|
+
const Presentation frame{
|
|
254
|
+
{frames.getValueAtIndex(rt, index + 1).asNumber(),
|
|
255
|
+
frames.getValueAtIndex(rt, index + 2).asNumber(),
|
|
256
|
+
frames.getValueAtIndex(rt, index + 3).asNumber(),
|
|
257
|
+
frames.getValueAtIndex(rt, index + 4).asNumber(),
|
|
258
|
+
frames.getValueAtIndex(rt, index + 5).asNumber()},
|
|
259
|
+
frames.getValueAtIndex(rt, index + 6).asNumber(),
|
|
260
|
+
frames.getValueAtIndex(rt, index + 7).asNumber()};
|
|
261
|
+
if (!std::isfinite(offset) || offset < 0 || offset > 1 ||
|
|
262
|
+
offset <= previousOffset || !finitePresentation(frame)) {
|
|
263
|
+
return Value(0);
|
|
264
|
+
}
|
|
265
|
+
previousOffset = offset;
|
|
266
|
+
keyframes.push_back({offset, frame});
|
|
267
|
+
}
|
|
268
|
+
if (keyframes.front().offset != 0 || keyframes.back().offset != 1) {
|
|
269
|
+
return Value(0);
|
|
270
|
+
}
|
|
271
|
+
return Value(animateKeyframes(
|
|
272
|
+
static_cast<uint64_t>(driverId),
|
|
273
|
+
{boolArg(args, count, 1), start},
|
|
274
|
+
target,
|
|
275
|
+
durationMs,
|
|
276
|
+
std::move(keyframes),
|
|
277
|
+
reduceMotion));
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
setHostFunction(
|
|
281
|
+
runtime, bindings, "rejectAnimation", 1,
|
|
282
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
283
|
+
if (count < 1 || !validDriverId(args[0].asNumber())) return Value(0);
|
|
284
|
+
return Value(rejectAnimation(
|
|
285
|
+
static_cast<uint64_t>(args[0].asNumber())));
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
setHostFunction(
|
|
289
|
+
runtime, bindings, "cancelAnimation", 3,
|
|
290
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
291
|
+
if (count < 3 || !validDriverId(args[0].asNumber())) {
|
|
292
|
+
return cancelResultArray(rt, false, {{0, 0, 0, 0, 0}, 0, 0});
|
|
293
|
+
}
|
|
294
|
+
const CancelResult result = cancelAnimation(
|
|
295
|
+
static_cast<uint64_t>(args[0].asNumber()),
|
|
296
|
+
static_cast<int32_t>(args[1].asNumber()),
|
|
297
|
+
static_cast<int32_t>(args[2].asNumber()) == 1);
|
|
298
|
+
return cancelResultArray(rt, result.handled, result.presentation);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
setHostFunction(
|
|
302
|
+
runtime, bindings, "destroyDriver", 1,
|
|
303
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
304
|
+
if (count >= 1 && validDriverId(args[0].asNumber())) {
|
|
305
|
+
destroyDriver(static_cast<uint64_t>(args[0].asNumber()));
|
|
306
|
+
}
|
|
307
|
+
return Value::undefined();
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
setHostFunction(
|
|
311
|
+
runtime, bindings, "onClipAnimationComplete", 1,
|
|
312
|
+
[state](Runtime &rt, const Value &, const Value *args, size_t count)
|
|
313
|
+
-> Value {
|
|
314
|
+
if (count < 1 || !args[0].isObject() ||
|
|
315
|
+
!args[0].getObject(rt).isFunction(rt)) {
|
|
316
|
+
return Value::undefined();
|
|
317
|
+
}
|
|
318
|
+
auto listener = std::make_shared<Function>(
|
|
319
|
+
args[0].getObject(rt).getFunction(rt));
|
|
320
|
+
const int32_t listenerId = ++state->nextListenerId;
|
|
321
|
+
state->listeners.emplace(listenerId, std::move(listener));
|
|
322
|
+
Object subscription(rt);
|
|
323
|
+
setHostFunction(
|
|
324
|
+
rt, subscription, "remove", 0,
|
|
325
|
+
[state, listenerId](
|
|
326
|
+
Runtime &, const Value &, const Value *, size_t) -> Value {
|
|
327
|
+
state->listeners.erase(listenerId);
|
|
328
|
+
return Value::undefined();
|
|
329
|
+
});
|
|
330
|
+
return subscription;
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
runtime.global().setProperty(runtime, "__SmoothClipView", bindings);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
void invalidateBindings() {
|
|
337
|
+
// Runs from SmoothClipModule.invalidate() on the JS thread while the
|
|
338
|
+
// runtime is still alive: completions must stop (the CallInvoker is about
|
|
339
|
+
// to die) and the listener jsi::Functions must be released against their
|
|
340
|
+
// own runtime.
|
|
341
|
+
auto state = bindingsState();
|
|
342
|
+
clearCompletionCallback(state.get());
|
|
343
|
+
state->listeners.clear();
|
|
344
|
+
state->runtime = nullptr;
|
|
345
|
+
state->callInvoker = nullptr;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
} // namespace smoothclip
|
|
349
|
+
|
|
350
|
+
// --- JNI surface -----------------------------------------------------------
|
|
351
|
+
|
|
352
|
+
namespace {
|
|
353
|
+
|
|
354
|
+
using namespace facebook;
|
|
355
|
+
|
|
356
|
+
jni::local_ref<BindingsInstallerHolder::javaobject> getBindingsInstaller(
|
|
357
|
+
jni::alias_ref<jni::JObject>) {
|
|
358
|
+
return BindingsInstallerHolder::newObjectCxxArgs(
|
|
359
|
+
[](jsi::Runtime &runtime, const std::shared_ptr<CallInvoker> &callInvoker) {
|
|
360
|
+
smoothclip::installBindings(runtime, callInvoker);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
void nativeRegisterView(
|
|
365
|
+
jni::alias_ref<jni::JObject>,
|
|
366
|
+
jdouble driverId,
|
|
367
|
+
jni::alias_ref<smoothclip::JSmoothClipView> view,
|
|
368
|
+
jdouble x,
|
|
369
|
+
jdouble y,
|
|
370
|
+
jdouble width,
|
|
371
|
+
jdouble height,
|
|
372
|
+
jdouble radius,
|
|
373
|
+
jdouble contentTranslateX,
|
|
374
|
+
jdouble contentTranslateY,
|
|
375
|
+
jdouble density,
|
|
376
|
+
jdouble widthPx,
|
|
377
|
+
jdouble heightPx) {
|
|
378
|
+
if (driverId <= 0 || !std::isfinite(driverId)) return;
|
|
379
|
+
smoothclip::registerViewAndroid(
|
|
380
|
+
static_cast<uint64_t>(driverId),
|
|
381
|
+
view,
|
|
382
|
+
smoothclip::Presentation{
|
|
383
|
+
{x, y, width, height, radius}, contentTranslateX, contentTranslateY},
|
|
384
|
+
density,
|
|
385
|
+
widthPx,
|
|
386
|
+
heightPx);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
void nativeSetViewHostGeometry(
|
|
390
|
+
jni::alias_ref<jni::JObject>,
|
|
391
|
+
jdouble driverId,
|
|
392
|
+
jni::alias_ref<smoothclip::JSmoothClipView> view,
|
|
393
|
+
jdouble density,
|
|
394
|
+
jdouble widthPx,
|
|
395
|
+
jdouble heightPx) {
|
|
396
|
+
if (driverId <= 0 || !std::isfinite(driverId)) return;
|
|
397
|
+
smoothclip::setViewHostGeometryAndroid(
|
|
398
|
+
static_cast<uint64_t>(driverId), view, density, widthPx, heightPx);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
void nativeUnregisterView(
|
|
402
|
+
jni::alias_ref<jni::JObject>,
|
|
403
|
+
jdouble driverId,
|
|
404
|
+
jni::alias_ref<smoothclip::JSmoothClipView> view) {
|
|
405
|
+
if (driverId <= 0 || !std::isfinite(driverId)) return;
|
|
406
|
+
smoothclip::unregisterViewAndroid(static_cast<uint64_t>(driverId), view);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
void nativeInvalidate(jni::alias_ref<jni::JObject>) {
|
|
410
|
+
smoothclip::invalidateBindings();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
} // namespace
|
|
414
|
+
|
|
415
|
+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
|
416
|
+
return facebook::jni::initialize(vm, [] {
|
|
417
|
+
facebook::jni::registerNatives(
|
|
418
|
+
"com/smoothclipview/SmoothClipBindings",
|
|
419
|
+
{
|
|
420
|
+
makeNativeMethod("getBindingsInstaller", getBindingsInstaller),
|
|
421
|
+
makeNativeMethod("nativeRegisterView", nativeRegisterView),
|
|
422
|
+
makeNativeMethod(
|
|
423
|
+
"nativeSetViewHostGeometry", nativeSetViewHostGeometry),
|
|
424
|
+
makeNativeMethod("nativeUnregisterView", nativeUnregisterView),
|
|
425
|
+
makeNativeMethod("nativeInvalidate", nativeInvalidate),
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
}
|