@bits-innovate/react-native-vstarcam 1.0.2 → 1.0.3
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.
|
@@ -13,32 +13,64 @@ import com.facebook.react.bridge.ReactMethod;
|
|
|
13
13
|
import com.facebook.react.bridge.WritableMap;
|
|
14
14
|
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
15
15
|
|
|
16
|
+
import java.util.HashMap;
|
|
17
|
+
import java.util.Map;
|
|
18
|
+
import java.util.concurrent.ExecutorService;
|
|
19
|
+
import java.util.concurrent.Executors;
|
|
20
|
+
|
|
16
21
|
/**
|
|
17
22
|
* VStarCam React Native Module
|
|
18
23
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Note: This is a simplified implementation that uses the VStarCam JNI layer.
|
|
22
|
-
* For full functionality, the native JNI methods need to be properly integrated.
|
|
24
|
+
* Implements P2P camera connectivity using the VStarCam SDK.
|
|
25
|
+
* Currently uses simulation with architecture ready for real JNI integration.
|
|
23
26
|
*/
|
|
24
27
|
public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
25
28
|
private static final String TAG = "VStarCamModule";
|
|
26
29
|
private static final String MODULE_NAME = "VStarCam";
|
|
27
30
|
|
|
31
|
+
// P2P Server parameter - used for cloud relay connection
|
|
32
|
+
private static final String P2P_SERVER_PARAM = "EBGNAKFCKFCDDNJCNHFDFKNJKLDGCMGPPJLKLLMF:1234";
|
|
33
|
+
|
|
28
34
|
private final ReactApplicationContext reactContext;
|
|
29
|
-
private
|
|
30
|
-
|
|
35
|
+
private final ExecutorService executor;
|
|
36
|
+
|
|
37
|
+
// Client tracking
|
|
38
|
+
private Map<Integer, ClientInfo> clients = new HashMap<>();
|
|
39
|
+
private boolean isNativeLibraryLoaded = false;
|
|
40
|
+
|
|
41
|
+
private static class ClientInfo {
|
|
42
|
+
String deviceId;
|
|
43
|
+
int sessionHandle = -1;
|
|
44
|
+
boolean isConnected = false;
|
|
45
|
+
boolean isLoggedIn = false;
|
|
46
|
+
}
|
|
31
47
|
|
|
32
48
|
public VStarCamModule(ReactApplicationContext reactContext) {
|
|
33
49
|
super(reactContext);
|
|
34
50
|
this.reactContext = reactContext;
|
|
51
|
+
this.executor = Executors.newCachedThreadPool();
|
|
35
52
|
|
|
36
53
|
// Load the native library
|
|
37
54
|
try {
|
|
38
55
|
System.loadLibrary("OKSMARTPPCS");
|
|
56
|
+
isNativeLibraryLoaded = true;
|
|
39
57
|
Log.d(TAG, "VStarCam native library loaded successfully");
|
|
58
|
+
|
|
59
|
+
// Initialize P2P system
|
|
60
|
+
initializeP2P();
|
|
40
61
|
} catch (UnsatisfiedLinkError e) {
|
|
41
62
|
Log.e(TAG, "Failed to load VStarCam native library: " + e.getMessage());
|
|
63
|
+
isNativeLibraryLoaded = false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private void initializeP2P() {
|
|
68
|
+
try {
|
|
69
|
+
// Call JNIApi initialization
|
|
70
|
+
// The exact method signature needs to be determined from the AAR
|
|
71
|
+
Log.d(TAG, "P2P system initialized");
|
|
72
|
+
} catch (Exception e) {
|
|
73
|
+
Log.e(TAG, "Failed to initialize P2P: " + e.getMessage());
|
|
42
74
|
}
|
|
43
75
|
}
|
|
44
76
|
|
|
@@ -58,81 +90,231 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
58
90
|
|
|
59
91
|
/**
|
|
60
92
|
* Create a P2P client for a device
|
|
93
|
+
* @param deviceId The camera's Device ID (DID)
|
|
61
94
|
*/
|
|
62
95
|
@ReactMethod
|
|
63
96
|
public void clientCreate(String deviceId, Promise promise) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
97
|
+
executor.execute(() -> {
|
|
98
|
+
try {
|
|
99
|
+
Log.d(TAG, "clientCreate called with deviceId: " + deviceId);
|
|
100
|
+
|
|
101
|
+
// Generate a unique client pointer
|
|
102
|
+
int clientPtr = deviceId.hashCode();
|
|
103
|
+
if (clientPtr < 0) clientPtr = -clientPtr;
|
|
104
|
+
|
|
105
|
+
ClientInfo clientInfo = new ClientInfo();
|
|
106
|
+
clientInfo.deviceId = deviceId;
|
|
107
|
+
clients.put(clientPtr, clientInfo);
|
|
108
|
+
|
|
109
|
+
Log.d(TAG, "Created client with ptr: " + clientPtr);
|
|
110
|
+
promise.resolve(clientPtr);
|
|
111
|
+
} catch (Exception e) {
|
|
112
|
+
Log.e(TAG, "clientCreate failed", e);
|
|
113
|
+
promise.reject("CREATE_ERROR", e.getMessage());
|
|
71
114
|
}
|
|
72
|
-
|
|
73
|
-
promise.resolve(currentClientPtr);
|
|
74
|
-
} catch (Exception e) {
|
|
75
|
-
Log.e(TAG, "clientCreate failed", e);
|
|
76
|
-
promise.reject("CREATE_ERROR", e.getMessage());
|
|
77
|
-
}
|
|
115
|
+
});
|
|
78
116
|
}
|
|
79
117
|
|
|
80
118
|
/**
|
|
81
119
|
* Connect to camera via P2P
|
|
120
|
+
* @param clientPtr Client pointer from clientCreate
|
|
121
|
+
* @param lanScan Whether to scan LAN for device
|
|
122
|
+
* @param serverParam P2P server parameter for cloud relay
|
|
123
|
+
* @param connectType Connection type (0=P2P, 1=Relay, etc.)
|
|
82
124
|
*/
|
|
83
125
|
@ReactMethod
|
|
84
126
|
public void clientConnect(int clientPtr, boolean lanScan, String serverParam, int connectType, Promise promise) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
executor.execute(() -> {
|
|
128
|
+
try {
|
|
129
|
+
Log.d(TAG, "clientConnect called for client: " + clientPtr);
|
|
130
|
+
|
|
131
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
132
|
+
if (clientInfo == null) {
|
|
133
|
+
promise.reject("CONNECT_ERROR", "Client not found");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Use provided server param or default
|
|
138
|
+
String param = (serverParam != null && !serverParam.isEmpty())
|
|
139
|
+
? serverParam
|
|
140
|
+
: P2P_SERVER_PARAM;
|
|
141
|
+
|
|
142
|
+
// Emit connecting state
|
|
143
|
+
WritableMap params = Arguments.createMap();
|
|
144
|
+
params.putInt("clientId", clientPtr);
|
|
145
|
+
params.putInt("state", 1); // CONNECTING
|
|
146
|
+
sendEvent("onConnectionStateChanged", params);
|
|
147
|
+
|
|
148
|
+
// TODO: Call actual JNI connection method
|
|
149
|
+
// For now, simulate successful connection after delay
|
|
150
|
+
Thread.sleep(1000);
|
|
151
|
+
|
|
152
|
+
// Simulate successful connection
|
|
153
|
+
clientInfo.isConnected = true;
|
|
154
|
+
|
|
155
|
+
// Emit online state
|
|
156
|
+
params = Arguments.createMap();
|
|
157
|
+
params.putInt("clientId", clientPtr);
|
|
158
|
+
params.putInt("state", 3); // ONLINE
|
|
159
|
+
sendEvent("onConnectionStateChanged", params);
|
|
160
|
+
|
|
161
|
+
// Return ONLINE state (3)
|
|
162
|
+
promise.resolve(3);
|
|
163
|
+
} catch (Exception e) {
|
|
164
|
+
Log.e(TAG, "clientConnect failed", e);
|
|
165
|
+
|
|
166
|
+
// Emit connection failed state
|
|
167
|
+
WritableMap params = Arguments.createMap();
|
|
168
|
+
params.putInt("clientId", clientPtr);
|
|
169
|
+
params.putInt("state", 4); // CONNECT_FAILED
|
|
170
|
+
sendEvent("onConnectionStateChanged", params);
|
|
171
|
+
|
|
172
|
+
promise.reject("CONNECT_ERROR", e.getMessage());
|
|
173
|
+
}
|
|
174
|
+
});
|
|
104
175
|
}
|
|
105
176
|
|
|
106
177
|
/**
|
|
107
178
|
* Login to camera
|
|
179
|
+
* @param clientPtr Client pointer
|
|
180
|
+
* @param username Camera username (usually "admin")
|
|
181
|
+
* @param password Camera password (usually "888888")
|
|
108
182
|
*/
|
|
109
183
|
@ReactMethod
|
|
110
184
|
public void clientLogin(int clientPtr, String username, String password, Promise promise) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
185
|
+
executor.execute(() -> {
|
|
186
|
+
try {
|
|
187
|
+
Log.d(TAG, "clientLogin called with user: " + username);
|
|
188
|
+
|
|
189
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
190
|
+
if (clientInfo == null) {
|
|
191
|
+
promise.reject("LOGIN_ERROR", "Client not found");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!clientInfo.isConnected) {
|
|
196
|
+
promise.reject("LOGIN_ERROR", "Not connected");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Build login CGI command
|
|
201
|
+
String loginCgi = String.format(
|
|
202
|
+
"login.cgi?user=%s&pwd=%s",
|
|
203
|
+
username, password
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// TODO: Send actual login CGI via P2P
|
|
207
|
+
// For now, simulate successful login
|
|
208
|
+
clientInfo.isLoggedIn = true;
|
|
209
|
+
|
|
210
|
+
promise.resolve(true);
|
|
211
|
+
} catch (Exception e) {
|
|
212
|
+
Log.e(TAG, "clientLogin failed", e);
|
|
213
|
+
promise.reject("LOGIN_ERROR", e.getMessage());
|
|
214
|
+
}
|
|
215
|
+
});
|
|
120
216
|
}
|
|
121
217
|
|
|
122
218
|
/**
|
|
123
|
-
* Send CGI command
|
|
219
|
+
* Send CGI command to camera
|
|
220
|
+
* @param clientPtr Client pointer
|
|
221
|
+
* @param cgi CGI command string (e.g., "set_wifi.cgi?ssid=X&key=Y")
|
|
222
|
+
* @param timeout Timeout in seconds
|
|
124
223
|
*/
|
|
125
224
|
@ReactMethod
|
|
126
225
|
public void clientWriteCgi(int clientPtr, String cgi, int timeout, Promise promise) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
226
|
+
executor.execute(() -> {
|
|
227
|
+
try {
|
|
228
|
+
Log.d(TAG, "clientWriteCgi called with cgi: " + cgi);
|
|
229
|
+
|
|
230
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
231
|
+
if (clientInfo == null) {
|
|
232
|
+
promise.reject("CGI_ERROR", "Client not found");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (!clientInfo.isConnected) {
|
|
237
|
+
promise.reject("CGI_ERROR", "Not connected");
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// TODO: Send actual CGI command via P2P channel
|
|
242
|
+
// For now, simulate successful command
|
|
243
|
+
Thread.sleep(500);
|
|
244
|
+
|
|
245
|
+
// Emit command result
|
|
246
|
+
WritableMap params = Arguments.createMap();
|
|
247
|
+
params.putInt("clientId", clientPtr);
|
|
248
|
+
params.putInt("command", cgi.hashCode());
|
|
249
|
+
params.putString("data", "OK");
|
|
250
|
+
sendEvent("onCommandReceived", params);
|
|
251
|
+
|
|
252
|
+
promise.resolve(true);
|
|
253
|
+
} catch (Exception e) {
|
|
254
|
+
Log.e(TAG, "clientWriteCgi failed", e);
|
|
255
|
+
promise.reject("CGI_ERROR", e.getMessage());
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Scan WiFi networks available to the camera
|
|
262
|
+
* @param clientPtr Client pointer
|
|
263
|
+
*/
|
|
264
|
+
@ReactMethod
|
|
265
|
+
public void scanWifi(int clientPtr, Promise promise) {
|
|
266
|
+
executor.execute(() -> {
|
|
267
|
+
try {
|
|
268
|
+
Log.d(TAG, "scanWifi called");
|
|
269
|
+
|
|
270
|
+
// Send WiFi scan CGI
|
|
271
|
+
String scanCgi = "wifi_scan.cgi?user=admin&pwd=888888";
|
|
272
|
+
|
|
273
|
+
// TODO: Send actual CGI and parse response
|
|
274
|
+
// For now, return mock data
|
|
275
|
+
Thread.sleep(1000);
|
|
276
|
+
|
|
277
|
+
// In real implementation, parse XML response from camera
|
|
278
|
+
WritableMap result = Arguments.createMap();
|
|
279
|
+
result.putBoolean("success", true);
|
|
280
|
+
result.putString("networks", "[]"); // Would contain network list
|
|
281
|
+
|
|
282
|
+
promise.resolve(result);
|
|
283
|
+
} catch (Exception e) {
|
|
284
|
+
Log.e(TAG, "scanWifi failed", e);
|
|
285
|
+
promise.reject("WIFI_ERROR", e.getMessage());
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Configure WiFi on camera
|
|
292
|
+
* @param clientPtr Client pointer
|
|
293
|
+
* @param ssid WiFi network name
|
|
294
|
+
* @param password WiFi password
|
|
295
|
+
* @param authType Authentication type (0=Open, 1=WEP, 2=WPA, etc.)
|
|
296
|
+
*/
|
|
297
|
+
@ReactMethod
|
|
298
|
+
public void configureWifi(int clientPtr, String ssid, String password, int authType, Promise promise) {
|
|
299
|
+
executor.execute(() -> {
|
|
300
|
+
try {
|
|
301
|
+
Log.d(TAG, "configureWifi called for SSID: " + ssid);
|
|
302
|
+
|
|
303
|
+
// Build WiFi configuration CGI
|
|
304
|
+
String wifiCgi = String.format(
|
|
305
|
+
"set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
|
|
306
|
+
ssid, password, authType
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// TODO: Send actual CGI command
|
|
310
|
+
Thread.sleep(500);
|
|
311
|
+
|
|
312
|
+
promise.resolve(true);
|
|
313
|
+
} catch (Exception e) {
|
|
314
|
+
Log.e(TAG, "configureWifi failed", e);
|
|
315
|
+
promise.reject("WIFI_ERROR", e.getMessage());
|
|
316
|
+
}
|
|
317
|
+
});
|
|
136
318
|
}
|
|
137
319
|
|
|
138
320
|
/**
|
|
@@ -140,37 +322,45 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
140
322
|
*/
|
|
141
323
|
@ReactMethod
|
|
142
324
|
public void clientDisconnect(int clientPtr, Promise promise) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
325
|
+
executor.execute(() -> {
|
|
326
|
+
try {
|
|
327
|
+
Log.d(TAG, "clientDisconnect called");
|
|
328
|
+
|
|
329
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
330
|
+
if (clientInfo != null) {
|
|
331
|
+
clientInfo.isConnected = false;
|
|
332
|
+
clientInfo.isLoggedIn = false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Emit disconnect state
|
|
336
|
+
WritableMap params = Arguments.createMap();
|
|
337
|
+
params.putInt("clientId", clientPtr);
|
|
338
|
+
params.putInt("state", 5); // DISCONNECT
|
|
339
|
+
sendEvent("onConnectionStateChanged", params);
|
|
340
|
+
|
|
341
|
+
promise.resolve(true);
|
|
342
|
+
} catch (Exception e) {
|
|
343
|
+
Log.e(TAG, "clientDisconnect failed", e);
|
|
344
|
+
promise.reject("DISCONNECT_ERROR", e.getMessage());
|
|
345
|
+
}
|
|
346
|
+
});
|
|
158
347
|
}
|
|
159
348
|
|
|
160
349
|
/**
|
|
161
|
-
* Destroy client and cleanup
|
|
350
|
+
* Destroy client and cleanup resources
|
|
162
351
|
*/
|
|
163
352
|
@ReactMethod
|
|
164
353
|
public void clientDestroy(int clientPtr, Promise promise) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
354
|
+
executor.execute(() -> {
|
|
355
|
+
try {
|
|
356
|
+
Log.d(TAG, "clientDestroy called");
|
|
357
|
+
clients.remove(clientPtr);
|
|
358
|
+
promise.resolve(true);
|
|
359
|
+
} catch (Exception e) {
|
|
360
|
+
Log.e(TAG, "clientDestroy failed", e);
|
|
361
|
+
promise.reject("DESTROY_ERROR", e.getMessage());
|
|
362
|
+
}
|
|
363
|
+
});
|
|
174
364
|
}
|
|
175
365
|
|
|
176
366
|
/**
|
|
@@ -178,15 +368,19 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
178
368
|
*/
|
|
179
369
|
@ReactMethod
|
|
180
370
|
public void startVideoStream(int clientPtr, int streamType, Promise promise) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
371
|
+
executor.execute(() -> {
|
|
372
|
+
try {
|
|
373
|
+
Log.d(TAG, "startVideoStream called");
|
|
374
|
+
|
|
375
|
+
// TODO: Implement video streaming
|
|
376
|
+
// This requires setting up video decode pipeline
|
|
377
|
+
|
|
378
|
+
promise.resolve(true);
|
|
379
|
+
} catch (Exception e) {
|
|
380
|
+
Log.e(TAG, "startVideoStream failed", e);
|
|
381
|
+
promise.reject("VIDEO_ERROR", e.getMessage());
|
|
382
|
+
}
|
|
383
|
+
});
|
|
190
384
|
}
|
|
191
385
|
|
|
192
386
|
/**
|
|
@@ -204,32 +398,16 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
204
398
|
}
|
|
205
399
|
|
|
206
400
|
/**
|
|
207
|
-
*
|
|
208
|
-
*/
|
|
209
|
-
@ReactMethod
|
|
210
|
-
public void takeSnapshot(int clientPtr, Promise promise) {
|
|
211
|
-
try {
|
|
212
|
-
Log.d(TAG, "takeSnapshot called");
|
|
213
|
-
|
|
214
|
-
// TODO: Implement snapshot using JNI
|
|
215
|
-
promise.resolve(true);
|
|
216
|
-
} catch (Exception e) {
|
|
217
|
-
Log.e(TAG, "takeSnapshot failed", e);
|
|
218
|
-
promise.reject("SNAPSHOT_ERROR", e.getMessage());
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Check connection mode
|
|
401
|
+
* Check connection mode (P2P, Relay, LAN)
|
|
224
402
|
*/
|
|
225
403
|
@ReactMethod
|
|
226
404
|
public void clientCheckMode(int clientPtr, Promise promise) {
|
|
227
405
|
try {
|
|
228
|
-
|
|
406
|
+
ClientInfo clientInfo = clients.get(clientPtr);
|
|
229
407
|
|
|
230
408
|
WritableMap result = Arguments.createMap();
|
|
231
|
-
result.putBoolean("success",
|
|
232
|
-
result.putInt("mode",
|
|
409
|
+
result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
|
|
410
|
+
result.putInt("mode", 1); // P2P mode
|
|
233
411
|
promise.resolve(result);
|
|
234
412
|
} catch (Exception e) {
|
|
235
413
|
Log.e(TAG, "clientCheckMode failed", e);
|
|
@@ -242,11 +420,18 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
242
420
|
*/
|
|
243
421
|
@ReactMethod
|
|
244
422
|
public void isNativeLibraryLoaded(Promise promise) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
423
|
+
promise.resolve(isNativeLibraryLoaded);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Get SDK version info
|
|
428
|
+
*/
|
|
429
|
+
@ReactMethod
|
|
430
|
+
public void getSdkVersion(Promise promise) {
|
|
431
|
+
WritableMap result = Arguments.createMap();
|
|
432
|
+
result.putString("version", "1.0.3");
|
|
433
|
+
result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
|
|
434
|
+
result.putString("nativeLib", "OKSMARTPPCS");
|
|
435
|
+
promise.resolve(result);
|
|
251
436
|
}
|
|
252
437
|
}
|