@shopify/react-native-skia 0.1.145 → 0.1.147
Sign up to get free protection for your applications and to get access to all the features.
- package/cpp/api/JsiSkContourMeasure.h +4 -4
- package/cpp/api/JsiSkDataFactory.h +3 -3
- package/cpp/api/JsiSkFont.h +1 -1
- package/cpp/api/JsiSkMatrix.h +9 -0
- package/cpp/api/JsiSkPath.h +2 -2
- package/cpp/api/JsiSkPathFactory.h +1 -1
- package/cpp/api/JsiSkPictureFactory.h +1 -1
- package/cpp/api/JsiSkRuntimeEffect.h +6 -6
- package/cpp/api/JsiSkRuntimeEffectFactory.h +1 -1
- package/cpp/jsi/JsiSimpleValueWrapper.h +27 -27
- package/cpp/jsi/JsiValueWrapper.h +127 -0
- package/cpp/rnskia/RNSkDrawView.cpp +41 -17
- package/cpp/rnskia/RNSkDrawView.h +17 -19
- package/cpp/rnskia/RNSkJsiViewApi.h +180 -166
- package/cpp/rnskia/values/RNSkComputedValue.h +11 -11
- package/cpp/rnskia/values/RNSkReadonlyValue.h +19 -19
- package/cpp/rnskia/values/RNSkValue.h +13 -13
- package/cpp/utils/RNSkLog.h +4 -4
- package/lib/commonjs/renderer/HostConfig.js +17 -1
- package/lib/commonjs/renderer/HostConfig.js.map +1 -1
- package/lib/commonjs/skia/types/Matrix.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkMatrix.js +4 -0
- package/lib/commonjs/skia/web/JsiSkMatrix.js.map +1 -1
- package/lib/commonjs/views/SkiaView.js +11 -27
- package/lib/commonjs/views/SkiaView.js.map +1 -1
- package/lib/commonjs/views/types.js.map +1 -1
- package/lib/module/renderer/HostConfig.js +17 -1
- package/lib/module/renderer/HostConfig.js.map +1 -1
- package/lib/module/skia/types/Matrix.js.map +1 -1
- package/lib/module/skia/web/JsiSkMatrix.js +4 -0
- package/lib/module/skia/web/JsiSkMatrix.js.map +1 -1
- package/lib/module/views/SkiaView.js +11 -26
- package/lib/module/views/SkiaView.js.map +1 -1
- package/lib/module/views/types.js.map +1 -1
- package/lib/typescript/src/skia/types/Matrix.d.ts +1 -0
- package/lib/typescript/src/skia/web/JsiSkMatrix.d.ts +1 -0
- package/lib/typescript/src/views/SkiaView.d.ts +1 -11
- package/lib/typescript/src/views/types.d.ts +5 -5
- package/package.json +1 -1
- package/src/renderer/HostConfig.ts +11 -1
- package/src/skia/types/Matrix.ts +1 -0
- package/src/skia/web/JsiSkMatrix.ts +4 -0
- package/src/views/SkiaView.tsx +17 -28
- package/src/views/types.ts +7 -6
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
#include <functional>
|
4
4
|
#include <memory>
|
5
|
+
#include <mutex>
|
5
6
|
#include <string>
|
6
7
|
#include <vector>
|
7
8
|
|
8
9
|
#include <JsiHostObject.h>
|
10
|
+
#include <JsiValueWrapper.h>
|
9
11
|
#include <RNSkDrawView.h>
|
10
12
|
#include <RNSkPlatformContext.h>
|
11
13
|
#include <RNSkValue.h>
|
@@ -14,96 +16,143 @@
|
|
14
16
|
namespace RNSkia {
|
15
17
|
using namespace facebook;
|
16
18
|
|
17
|
-
using
|
18
|
-
|
19
|
-
drawCallback = nullptr;
|
19
|
+
using RNSkViewInfo = struct RNSkViewInfo {
|
20
|
+
RNSkViewInfo() {
|
20
21
|
view = nullptr;
|
21
22
|
}
|
22
|
-
std::shared_ptr<FunctionWrapper> drawCallback;
|
23
23
|
std::shared_ptr<RNSkDrawView> view;
|
24
|
+
std::unordered_map<std::string, JsiValueWrapper> props;
|
24
25
|
};
|
25
26
|
|
26
|
-
class RNSkJsiViewApi : public JsiHostObject {
|
27
|
+
class RNSkJsiViewApi : public JsiHostObject, public std::enable_shared_from_this<RNSkJsiViewApi> {
|
27
28
|
public:
|
28
|
-
|
29
|
-
|
29
|
+
/**
|
30
|
+
Sets a custom property on a view given a view id. The property name/value will
|
31
|
+
be stored in a map alongside the id of the view and propagated to the view when
|
32
|
+
needed.
|
33
|
+
*/
|
34
|
+
JSI_HOST_FUNCTION(setJsiProperty) {
|
35
|
+
if (count != 3) {
|
30
36
|
_platformContext->raiseError(
|
31
|
-
std::string("
|
37
|
+
std::string("setJsiProperty: Expected 3 arguments, got " +
|
32
38
|
std::to_string(count) + "."));
|
33
39
|
return jsi::Value::undefined();
|
34
40
|
}
|
35
41
|
|
36
42
|
if (!arguments[0].isNumber()) {
|
37
43
|
_platformContext->raiseError(
|
38
|
-
"
|
44
|
+
"setJsiProperty: First argument must be a number");
|
39
45
|
return jsi::Value::undefined();
|
40
46
|
}
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
_platformContext->raiseError(
|
46
|
-
"setDrawCallback: Second argument must be a function");
|
47
|
-
return jsi::Value::undefined();
|
48
|
-
}
|
49
|
-
if (!arguments[1].asObject(runtime).isFunction(runtime)) {
|
50
|
-
_platformContext->raiseError(
|
51
|
-
"setDrawCallback: Second argument must be a function");
|
52
|
-
return jsi::Value::undefined();
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
// find skia draw view
|
57
|
-
int nativeId = arguments[0].asNumber();
|
48
|
+
if (!arguments[1].isString()) {
|
49
|
+
_platformContext->raiseError(
|
50
|
+
"setJsiProperty: Second argument must be the name of the property to set.");
|
58
51
|
|
59
|
-
|
60
|
-
auto info = getEnsuredCallbackInfo(nativeId);
|
61
|
-
if (arguments[1].isUndefined()) {
|
62
|
-
info->drawCallback = nullptr;
|
63
|
-
} else {
|
64
|
-
info->drawCallback = std::make_shared<FunctionWrapper>(
|
65
|
-
arguments[1].asObject(runtime).asFunction(runtime));
|
52
|
+
return jsi::Value::undefined();
|
66
53
|
}
|
54
|
+
auto nativeId = arguments[0].asNumber();
|
55
|
+
auto info = getEnsuredViewInfo(nativeId);
|
67
56
|
|
68
|
-
|
69
|
-
|
57
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
58
|
+
info->props.emplace(arguments[1].asString(runtime).utf8(runtime), JsiValueWrapper(runtime, arguments[2]));
|
59
|
+
|
60
|
+
// Now let's see if we have a view that we can update
|
61
|
+
if(info->view != nullptr) {
|
62
|
+
// Update view!
|
70
63
|
info->view->setNativeId(nativeId);
|
71
|
-
info->view->
|
64
|
+
info->view->setJsiProperties(info->props);
|
65
|
+
info->props.clear();
|
72
66
|
}
|
73
67
|
|
74
68
|
return jsi::Value::undefined();
|
75
69
|
}
|
76
70
|
|
77
|
-
|
78
|
-
|
71
|
+
/**
|
72
|
+
Calls a custom command / method on a view by the view id.
|
73
|
+
*/
|
74
|
+
JSI_HOST_FUNCTION(callJsiMethod) {
|
75
|
+
if (count < 2) {
|
79
76
|
_platformContext->raiseError(
|
80
|
-
std::string("
|
77
|
+
std::string("callCustomCommand: Expected at least 2 arguments, got " +
|
81
78
|
std::to_string(count) + "."));
|
79
|
+
|
82
80
|
return jsi::Value::undefined();
|
83
81
|
}
|
84
82
|
|
85
83
|
if (!arguments[0].isNumber()) {
|
86
84
|
_platformContext->raiseError(
|
87
|
-
"
|
85
|
+
"callCustomCommand: First argument must be a number");
|
86
|
+
|
88
87
|
return jsi::Value::undefined();
|
89
88
|
}
|
90
89
|
|
91
|
-
|
92
|
-
|
90
|
+
if (!arguments[1].isString()) {
|
91
|
+
_platformContext->raiseError(
|
92
|
+
"callCustomCommand: Second argument must be the name of the action to call.");
|
93
93
|
|
94
|
-
|
95
|
-
if (info->view != nullptr) {
|
96
|
-
info->view->requestRedraw();
|
94
|
+
return jsi::Value::undefined();
|
97
95
|
}
|
98
|
-
|
96
|
+
|
97
|
+
auto nativeId = arguments[0].asNumber();
|
98
|
+
auto action = arguments[1].asString(runtime).utf8(runtime);
|
99
|
+
|
100
|
+
auto info = getEnsuredViewInfo(nativeId);
|
101
|
+
|
102
|
+
if(info->view == nullptr) {
|
103
|
+
throw jsi::JSError(runtime,
|
104
|
+
std::string("callCustomCommand: Could not call action " + action +
|
105
|
+
" on view - view not ready.").c_str());
|
106
|
+
|
107
|
+
return jsi::Value::undefined();
|
108
|
+
}
|
109
|
+
|
110
|
+
// Get arguments
|
111
|
+
size_t paramsCount = count - 2;
|
112
|
+
const jsi::Value* params = paramsCount > 0 ? &arguments[2] : nullptr;
|
113
|
+
return info->view->callJsiMethod(runtime, action, params, paramsCount);
|
99
114
|
}
|
100
|
-
|
115
|
+
|
116
|
+
JSI_HOST_FUNCTION(requestRedraw) {
|
117
|
+
if (count < 2) {
|
118
|
+
_platformContext->raiseError(
|
119
|
+
std::string("requestRedraw: Expected 2 arguments, got " + std::to_string(count) + "."));
|
120
|
+
|
121
|
+
return jsi::Value::undefined();
|
122
|
+
}
|
123
|
+
|
124
|
+
if (!arguments[0].isNumber()) {
|
125
|
+
_platformContext->raiseError(
|
126
|
+
"requestRedraw: First argument must be a number");
|
127
|
+
|
128
|
+
return jsi::Value::undefined();
|
129
|
+
}
|
130
|
+
|
131
|
+
// find Skia View
|
132
|
+
int nativeId = arguments[0].asNumber();
|
133
|
+
|
134
|
+
auto info = getEnsuredViewInfo(nativeId);
|
135
|
+
if (info->view != nullptr) {
|
136
|
+
info->view->requestRedraw();
|
137
|
+
}
|
138
|
+
return jsi::Value::undefined();
|
139
|
+
}
|
140
|
+
|
101
141
|
JSI_HOST_FUNCTION(makeImageSnapshot) {
|
102
|
-
|
103
|
-
|
142
|
+
if (count < 1) {
|
143
|
+
_platformContext->raiseError(std::string("makeImageSnapshot: Expected at least 1 argument, got " + std::to_string(count) + "."));
|
144
|
+
return jsi::Value::undefined();
|
145
|
+
}
|
146
|
+
|
147
|
+
if (!arguments[0].isNumber()) {
|
148
|
+
_platformContext->raiseError("makeImageSnapshot: First argument must be a number");
|
149
|
+
return jsi::Value::undefined();
|
150
|
+
}
|
151
|
+
|
152
|
+
// find Skia view
|
104
153
|
int nativeId = arguments[0].asNumber();
|
105
154
|
sk_sp<SkImage> image;
|
106
|
-
auto info =
|
155
|
+
auto info = getEnsuredViewInfo(nativeId);
|
107
156
|
if (info->view != nullptr) {
|
108
157
|
if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) {
|
109
158
|
auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
|
@@ -112,88 +161,66 @@ public:
|
|
112
161
|
image = info->view->makeImageSnapshot(nullptr);
|
113
162
|
}
|
114
163
|
if(image == nullptr) {
|
115
|
-
jsi::
|
164
|
+
throw jsi::JSError(runtime, "Could not create image from current surface.");
|
116
165
|
return jsi::Value::undefined();
|
117
166
|
}
|
118
167
|
return jsi::Object::createFromHostObject(runtime, std::make_shared<JsiSkImage>(_platformContext, image));
|
119
168
|
}
|
120
|
-
jsi::
|
169
|
+
throw jsi::JSError(runtime, "No Skia View currently available.");
|
121
170
|
return jsi::Value::undefined();
|
122
171
|
}
|
123
|
-
|
124
|
-
JSI_HOST_FUNCTION(setDrawMode) {
|
125
|
-
if (count != 2) {
|
126
|
-
_platformContext->raiseError(
|
127
|
-
std::string("setDrawMode: Expected 2 arguments, got " +
|
128
|
-
std::to_string(count) + "."));
|
129
|
-
return jsi::Value::undefined();
|
130
|
-
}
|
131
172
|
|
132
|
-
if (!arguments[0].isNumber()) {
|
133
|
-
_platformContext->raiseError(
|
134
|
-
"setDrawMode: First argument must be a number");
|
135
|
-
return jsi::Value::undefined();
|
136
|
-
}
|
137
|
-
|
138
|
-
// find skia draw view
|
139
|
-
int nativeId = arguments[0].asNumber();
|
140
|
-
auto info = getEnsuredCallbackInfo(nativeId);
|
141
|
-
if (info->view != nullptr) {
|
142
|
-
auto nextMode = arguments[1].asString(runtime).utf8(runtime);
|
143
|
-
if(nextMode.compare("continuous") == 0) {
|
144
|
-
info->view->setDrawingMode(RNSkDrawingMode::Continuous);
|
145
|
-
} else {
|
146
|
-
info->view->setDrawingMode(RNSkDrawingMode::Default);
|
147
|
-
}
|
148
|
-
}
|
149
|
-
return jsi::Value::undefined();
|
150
|
-
}
|
151
|
-
|
152
173
|
JSI_HOST_FUNCTION(registerValuesInView) {
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
}
|
158
|
-
|
159
|
-
// Get identifier of native SkiaView
|
160
|
-
int nativeId = arguments[0].asNumber();
|
161
|
-
|
162
|
-
// Get values that should be added as dependencies
|
163
|
-
auto values = arguments[1].asObject(runtime).asArray(runtime);
|
164
|
-
std::vector<std::function<void()>> unsubscribers;
|
165
|
-
const std::size_t size = values.size(runtime);
|
166
|
-
unsubscribers.reserve(size);
|
167
|
-
for(size_t i=0; i<size; ++i) {
|
168
|
-
auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
|
169
|
-
|
170
|
-
if(value != nullptr) {
|
171
|
-
// Add change listener
|
172
|
-
unsubscribers.push_back(value->addListener([this, nativeId](jsi::Runtime&){
|
173
|
-
requestRedrawView(nativeId);
|
174
|
-
}));
|
174
|
+
// Check params
|
175
|
+
if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) {
|
176
|
+
throw jsi::JSError(runtime, "Expected array of Values as second parameter");
|
177
|
+
return jsi::Value::undefined();
|
175
178
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
for(
|
186
|
-
|
179
|
+
|
180
|
+
// Get identifier of native SkiaView
|
181
|
+
int nativeId = arguments[0].asNumber();
|
182
|
+
|
183
|
+
// Get values that should be added as dependencies
|
184
|
+
auto values = arguments[1].asObject(runtime).asArray(runtime);
|
185
|
+
std::vector<std::function<void()>> unsubscribers;
|
186
|
+
const std::size_t size = values.size(runtime);
|
187
|
+
unsubscribers.reserve(size);
|
188
|
+
for(size_t i=0; i<size; ++i) {
|
189
|
+
auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
|
190
|
+
|
191
|
+
if(value != nullptr) {
|
192
|
+
// Add change listener
|
193
|
+
unsubscribers.push_back(value->addListener([weakSelf = weak_from_this(), nativeId](jsi::Runtime&){
|
194
|
+
auto self = weakSelf.lock();
|
195
|
+
if(self) {
|
196
|
+
auto info = self->getEnsuredViewInfo(nativeId);
|
197
|
+
if(info->view != nullptr) {
|
198
|
+
info->view->requestRedraw();
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}));
|
202
|
+
}
|
187
203
|
}
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
204
|
+
|
205
|
+
// Return unsubscribe method that unsubscribes to all values
|
206
|
+
// that we subscribed to.
|
207
|
+
return jsi::Function::createFromHostFunction(runtime,
|
208
|
+
jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
|
209
|
+
0,
|
210
|
+
JSI_HOST_FUNCTION_LAMBDA {
|
211
|
+
// decrease dependency count on the Skia View
|
212
|
+
for(auto &unsub : unsubscribers) {
|
213
|
+
unsub();
|
214
|
+
}
|
215
|
+
return jsi::Value::undefined();
|
216
|
+
});
|
217
|
+
}
|
218
|
+
|
219
|
+
JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setJsiProperty),
|
220
|
+
JSI_EXPORT_FUNC(RNSkJsiViewApi, callJsiMethod),
|
221
|
+
JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView),
|
222
|
+
JSI_EXPORT_FUNC(RNSkJsiViewApi, requestRedraw),
|
223
|
+
JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot))
|
197
224
|
|
198
225
|
/**
|
199
226
|
* Constructor
|
@@ -203,7 +230,7 @@ public:
|
|
203
230
|
: JsiHostObject(), _platformContext(platformContext) {}
|
204
231
|
|
205
232
|
/**
|
206
|
-
* Invalidates the
|
233
|
+
* Invalidates the Skia View Api object
|
207
234
|
*/
|
208
235
|
void invalidate() {
|
209
236
|
unregisterAll();
|
@@ -214,11 +241,12 @@ public:
|
|
214
241
|
*/
|
215
242
|
void unregisterAll() {
|
216
243
|
// Unregister all views
|
217
|
-
auto tempList =
|
244
|
+
auto tempList = _viewInfos;
|
218
245
|
for (const auto& info : tempList) {
|
219
246
|
unregisterSkiaDrawView(info.first);
|
220
247
|
}
|
221
|
-
|
248
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
249
|
+
_viewInfos.clear();
|
222
250
|
}
|
223
251
|
|
224
252
|
/**
|
@@ -227,12 +255,12 @@ public:
|
|
227
255
|
* @param view View to register
|
228
256
|
*/
|
229
257
|
void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
|
230
|
-
auto info =
|
258
|
+
auto info = getEnsuredViewInfo(nativeId);
|
259
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
231
260
|
info->view = view;
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
}
|
261
|
+
info->view->setNativeId(nativeId);
|
262
|
+
info->view->setJsiProperties(info->props);
|
263
|
+
info->props.clear();
|
236
264
|
}
|
237
265
|
|
238
266
|
/**
|
@@ -240,37 +268,34 @@ public:
|
|
240
268
|
* @param nativeId View id
|
241
269
|
*/
|
242
270
|
void unregisterSkiaDrawView(size_t nativeId) {
|
243
|
-
if (
|
271
|
+
if (_viewInfos.count(nativeId) == 0) {
|
244
272
|
return;
|
245
273
|
}
|
246
|
-
auto info =
|
247
|
-
|
248
|
-
|
249
|
-
}
|
274
|
+
auto info = getEnsuredViewInfo(nativeId);
|
275
|
+
|
276
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
250
277
|
info->view = nullptr;
|
251
|
-
|
252
|
-
_callbackInfos.erase(nativeId);
|
278
|
+
_viewInfos.erase(nativeId);
|
253
279
|
}
|
254
|
-
|
280
|
+
|
255
281
|
/**
|
256
282
|
Sets a skia draw view for the given id. This function can be used
|
257
283
|
to mark that an underlying SkiaView is not available (it could be
|
258
284
|
removed due to ex. a transition). The view can be set to a nullptr
|
259
|
-
or a valid view, effectively toggling the view's availability.
|
260
|
-
a valid view is set, the setDrawCallback method is called on the
|
261
|
-
view (if a valid callback exists).
|
285
|
+
or a valid view, effectively toggling the view's availability.
|
262
286
|
*/
|
263
287
|
void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
|
264
|
-
if (
|
288
|
+
if (_viewInfos.find(nativeId) == _viewInfos.end()) {
|
265
289
|
return;
|
266
290
|
}
|
267
|
-
auto info =
|
268
|
-
|
291
|
+
auto info = getEnsuredViewInfo(nativeId);
|
292
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
293
|
+
if (view != nullptr) {
|
269
294
|
info->view = view;
|
270
295
|
info->view->setNativeId(nativeId);
|
271
|
-
info->view->
|
272
|
-
|
273
|
-
|
296
|
+
info->view->setJsiProperties(info->props);
|
297
|
+
info->props.clear();
|
298
|
+
} else if(view == nullptr) {
|
274
299
|
info->view = view;
|
275
300
|
}
|
276
301
|
}
|
@@ -281,28 +306,17 @@ private:
|
|
281
306
|
* @param nativeId View id
|
282
307
|
* @return The callback info object for the requested view
|
283
308
|
*/
|
284
|
-
|
285
|
-
if (
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
return &_callbackInfos.at(nativeId);
|
290
|
-
}
|
291
|
-
|
292
|
-
/**
|
293
|
-
Send a redraw request to the view
|
294
|
-
*/
|
295
|
-
void requestRedrawView(size_t nativeId) {
|
296
|
-
auto info = getEnsuredCallbackInfo(nativeId);
|
297
|
-
if(info->view != nullptr) {
|
298
|
-
info->view->requestRedraw();
|
309
|
+
RNSkViewInfo *getEnsuredViewInfo(size_t nativeId) {
|
310
|
+
if (_viewInfos.count(nativeId) == 0) {
|
311
|
+
RNSkViewInfo info;
|
312
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
313
|
+
_viewInfos.emplace(nativeId, info);
|
299
314
|
}
|
315
|
+
return &_viewInfos.at(nativeId);
|
300
316
|
}
|
301
|
-
|
302
|
-
|
303
|
-
std::unordered_map<size_t, CallbackInfo> _callbackInfos;
|
304
|
-
|
305
|
-
// Platform context
|
317
|
+
|
318
|
+
std::unordered_map<size_t, RNSkViewInfo> _viewInfos;
|
306
319
|
std::shared_ptr<RNSkPlatformContext> _platformContext;
|
320
|
+
std::mutex _mutex;
|
307
321
|
};
|
308
322
|
} // namespace RNSkia
|
@@ -31,32 +31,32 @@ public:
|
|
31
31
|
// Verify input
|
32
32
|
if(!arguments[0].isObject() ||
|
33
33
|
!arguments[0].asObject(runtime).isFunction(runtime)) {
|
34
|
-
jsi::
|
34
|
+
throw jsi::JSError(runtime, "Expected callback function as first parameter");
|
35
35
|
}
|
36
|
-
|
36
|
+
|
37
37
|
if(!arguments[1].isObject() ||
|
38
38
|
!arguments[1].asObject(runtime).isArray(runtime)) {
|
39
|
-
jsi::
|
39
|
+
throw jsi::JSError(runtime, "Expected array of dependencies as second parameter");
|
40
40
|
}
|
41
|
-
|
41
|
+
|
42
42
|
// Get callback for calculating result
|
43
43
|
_callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
|
44
44
|
}
|
45
|
-
|
45
|
+
|
46
46
|
void invalidate() override {
|
47
47
|
RNSkReadonlyValue::invalidate();
|
48
|
-
|
48
|
+
|
49
49
|
// Unregister listeners
|
50
50
|
for(const auto &unsubscribe: _unsubscribers) {
|
51
51
|
unsubscribe();
|
52
52
|
}
|
53
53
|
_unsubscribers.clear();
|
54
54
|
}
|
55
|
-
|
55
|
+
|
56
56
|
void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) {
|
57
57
|
// Save dependencies
|
58
58
|
std::vector<std::shared_ptr<RNSkReadonlyValue>> dependencies;
|
59
|
-
|
59
|
+
|
60
60
|
// Ensure that all dependencies are Values
|
61
61
|
auto deps = arguments[1].asObject(runtime).asArray(runtime);
|
62
62
|
const std::size_t size = deps.size(runtime);
|
@@ -73,7 +73,7 @@ public:
|
|
73
73
|
}
|
74
74
|
dependencies.push_back(value);
|
75
75
|
}
|
76
|
-
|
76
|
+
|
77
77
|
// register change handler on dependencies
|
78
78
|
_unsubscribers.reserve(_unsubscribers.size() + size);
|
79
79
|
for(const auto &dep: dependencies) {
|
@@ -85,11 +85,11 @@ public:
|
|
85
85
|
}
|
86
86
|
}));
|
87
87
|
}
|
88
|
-
|
88
|
+
|
89
89
|
// Set initial value
|
90
90
|
dependencyUpdated(runtime);
|
91
91
|
}
|
92
|
-
|
92
|
+
|
93
93
|
private:
|
94
94
|
void dependencyUpdated(jsi::Runtime &runtime) {
|
95
95
|
// Calculate new value
|
@@ -29,7 +29,7 @@ public:
|
|
29
29
|
: JsiSkHostObject(platformContext),
|
30
30
|
_valueHolder(std::make_unique<JsiSimpleValueWrapper>(*platformContext->getJsRuntime()))
|
31
31
|
{ }
|
32
|
-
|
32
|
+
|
33
33
|
virtual ~RNSkReadonlyValue() {
|
34
34
|
invalidate();
|
35
35
|
}
|
@@ -37,21 +37,21 @@ public:
|
|
37
37
|
JSI_PROPERTY_GET(__typename__) {
|
38
38
|
return jsi::String::createFromUtf8(runtime, "RNSkValue");
|
39
39
|
}
|
40
|
-
|
40
|
+
|
41
41
|
JSI_PROPERTY_GET(current) {
|
42
42
|
return getCurrent(runtime);
|
43
43
|
}
|
44
|
-
|
44
|
+
|
45
45
|
JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__),
|
46
46
|
JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current))
|
47
|
-
|
47
|
+
|
48
48
|
JSI_HOST_FUNCTION(addListener) {
|
49
49
|
if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) {
|
50
|
-
jsi::
|
50
|
+
throw jsi::JSError(runtime, "Expected function as first parameter.");
|
51
51
|
return jsi::Value::undefined();
|
52
52
|
}
|
53
53
|
auto callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
|
54
|
-
|
54
|
+
|
55
55
|
auto unsubscribe = addListener([weakSelf = weak_from_this(),
|
56
56
|
callback = std::move(callback)](jsi::Runtime& runtime){
|
57
57
|
auto self = weakSelf.lock();
|
@@ -60,7 +60,7 @@ public:
|
|
60
60
|
callback->call(runtime, selfReadonlyValue->get_current(runtime));
|
61
61
|
}
|
62
62
|
});
|
63
|
-
|
63
|
+
|
64
64
|
return jsi::Function::createFromHostFunction(runtime,
|
65
65
|
jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
|
66
66
|
0,
|
@@ -69,17 +69,17 @@ public:
|
|
69
69
|
return jsi::Value::undefined();
|
70
70
|
});
|
71
71
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
|
73
|
+
|
74
|
+
|
75
75
|
JSI_HOST_FUNCTION(__invalidate) {
|
76
76
|
invalidate();
|
77
77
|
return jsi::Value::undefined();
|
78
78
|
}
|
79
|
-
|
79
|
+
|
80
80
|
JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener),
|
81
81
|
JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate))
|
82
|
-
|
82
|
+
|
83
83
|
/**
|
84
84
|
* Adds a callback that will be called whenever the value changes
|
85
85
|
* @param cb Callback
|
@@ -96,7 +96,7 @@ public:
|
|
96
96
|
}
|
97
97
|
};
|
98
98
|
}
|
99
|
-
|
99
|
+
|
100
100
|
/**
|
101
101
|
Updates the underlying value and notifies all listeners about the change.
|
102
102
|
Listeners are only notified if the value was actually changed for numeric, boolean and string
|
@@ -111,7 +111,7 @@ public:
|
|
111
111
|
notifyListeners(runtime);
|
112
112
|
}
|
113
113
|
}
|
114
|
-
|
114
|
+
|
115
115
|
/**
|
116
116
|
Override to implement invalidation logic for the value. In the base class this function
|
117
117
|
clears all subscribers.
|
@@ -120,13 +120,13 @@ public:
|
|
120
120
|
std::lock_guard<std::mutex> lock(_mutex);
|
121
121
|
_listeners.clear();
|
122
122
|
}
|
123
|
-
|
123
|
+
|
124
124
|
jsi::Value getCurrent(jsi::Runtime &runtime) {
|
125
125
|
return _valueHolder->getCurrent(runtime);
|
126
126
|
}
|
127
|
-
|
127
|
+
|
128
128
|
protected:
|
129
|
-
|
129
|
+
|
130
130
|
/**
|
131
131
|
Notifies listeners about changes
|
132
132
|
@param runtime Current JS Runtime
|
@@ -141,7 +141,7 @@ protected:
|
|
141
141
|
listener.second(runtime);
|
142
142
|
}
|
143
143
|
}
|
144
|
-
|
144
|
+
|
145
145
|
/**
|
146
146
|
Removes a subscription listeners
|
147
147
|
@param listenerId identifier of listener to remove
|
@@ -153,7 +153,7 @@ protected:
|
|
153
153
|
|
154
154
|
private:
|
155
155
|
std::unique_ptr<JsiSimpleValueWrapper> _valueHolder;
|
156
|
-
|
156
|
+
|
157
157
|
long _listenerId = 0;
|
158
158
|
std::unordered_map<long, std::function<void(jsi::Runtime&)>> _listeners;
|
159
159
|
std::mutex _mutex;
|