basalt-core 0.0.0-rc5
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/LICENSE +21 -0
- package/dist/cli/basalt.d.ts +3 -0
- package/dist/cli/basalt.d.ts.map +1 -0
- package/dist/cli/basalt.js +47 -0
- package/dist/cli/basalt.js.map +1 -0
- package/dist/cli/bundle-cli.d.ts +12 -0
- package/dist/cli/bundle-cli.d.ts.map +1 -0
- package/dist/cli/bundle-cli.js +124 -0
- package/dist/cli/bundle-cli.js.map +1 -0
- package/dist/cli/bundleWithAssets.d.ts +79 -0
- package/dist/cli/bundleWithAssets.d.ts.map +1 -0
- package/dist/cli/bundleWithAssets.js +198 -0
- package/dist/cli/bundleWithAssets.js.map +1 -0
- package/dist/cli/desktop.d.ts +339 -0
- package/dist/cli/desktop.d.ts.map +1 -0
- package/dist/cli/desktop.js +1029 -0
- package/dist/cli/desktop.js.map +1 -0
- package/dist/cli/doctor.d.ts +31 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +283 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +77 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +442 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/metro.d.ts +49 -0
- package/dist/cli/metro.d.ts.map +1 -0
- package/dist/cli/metro.js +148 -0
- package/dist/cli/metro.js.map +1 -0
- package/dist/cli/packageApp.d.ts +102 -0
- package/dist/cli/packageApp.d.ts.map +1 -0
- package/dist/cli/packageApp.js +319 -0
- package/dist/cli/packageApp.js.map +1 -0
- package/dist/cli/steps.d.ts +34 -0
- package/dist/cli/steps.d.ts.map +1 -0
- package/dist/cli/steps.js +53 -0
- package/dist/cli/steps.js.map +1 -0
- package/dist/metro-config.d.ts +168 -0
- package/dist/metro-config.d.ts.map +1 -0
- package/dist/metro-config.js +671 -0
- package/dist/metro-config.js.map +1 -0
- package/dist/react-native.config.d.ts +7 -0
- package/dist/react-native.config.d.ts.map +1 -0
- package/dist/react-native.config.js +80 -0
- package/dist/react-native.config.js.map +1 -0
- package/dist/src/DragSource.d.ts +52 -0
- package/dist/src/DragSource.d.ts.map +1 -0
- package/dist/src/DragSource.js +97 -0
- package/dist/src/DragSource.js.map +1 -0
- package/dist/src/DropTarget.d.ts +58 -0
- package/dist/src/DropTarget.d.ts.map +1 -0
- package/dist/src/DropTarget.js +131 -0
- package/dist/src/DropTarget.js.map +1 -0
- package/dist/src/KeyHandler.d.ts +57 -0
- package/dist/src/KeyHandler.d.ts.map +1 -0
- package/dist/src/KeyHandler.js +48 -0
- package/dist/src/KeyHandler.js.map +1 -0
- package/dist/src/Menu.d.ts +72 -0
- package/dist/src/Menu.d.ts.map +1 -0
- package/dist/src/Menu.js +179 -0
- package/dist/src/Menu.js.map +1 -0
- package/dist/src/TitleBar.d.ts +75 -0
- package/dist/src/TitleBar.d.ts.map +1 -0
- package/dist/src/TitleBar.js +236 -0
- package/dist/src/TitleBar.js.map +1 -0
- package/dist/src/Window.d.ts +87 -0
- package/dist/src/Window.d.ts.map +1 -0
- package/dist/src/Window.js +248 -0
- package/dist/src/Window.js.map +1 -0
- package/dist/src/closeRequest.d.ts +55 -0
- package/dist/src/closeRequest.d.ts.map +1 -0
- package/dist/src/closeRequest.js +134 -0
- package/dist/src/closeRequest.js.map +1 -0
- package/dist/src/index.d.ts +45 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +92 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/overrides/Alert.d.ts +69 -0
- package/dist/src/overrides/Alert.d.ts.map +1 -0
- package/dist/src/overrides/Alert.js +112 -0
- package/dist/src/overrides/Alert.js.map +1 -0
- package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
- package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
- package/dist/src/overrides/BaseViewConfig.js +72 -0
- package/dist/src/overrides/BaseViewConfig.js.map +1 -0
- package/dist/src/overrides/Platform.linux.d.ts +10 -0
- package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
- package/dist/src/overrides/Platform.linux.js +15 -0
- package/dist/src/overrides/Platform.linux.js.map +1 -0
- package/dist/src/overrides/Platform.macos.d.ts +10 -0
- package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
- package/dist/src/overrides/Platform.macos.js +15 -0
- package/dist/src/overrides/Platform.macos.js.map +1 -0
- package/dist/src/overrides/Platform.windows.d.ts +10 -0
- package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
- package/dist/src/overrides/Platform.windows.js +15 -0
- package/dist/src/overrides/Platform.windows.js.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
- package/dist/src/overrides/RefreshControl.d.ts +52 -0
- package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
- package/dist/src/overrides/RefreshControl.js +92 -0
- package/dist/src/overrides/RefreshControl.js.map +1 -0
- package/dist/src/overrides/ScrollView.d.ts +39 -0
- package/dist/src/overrides/ScrollView.d.ts.map +1 -0
- package/dist/src/overrides/ScrollView.js +59 -0
- package/dist/src/overrides/ScrollView.js.map +1 -0
- package/dist/src/overrides/Share.d.ts +96 -0
- package/dist/src/overrides/Share.d.ts.map +1 -0
- package/dist/src/overrides/Share.js +97 -0
- package/dist/src/overrides/Share.js.map +1 -0
- package/dist/src/overrides/TextInput.d.ts +81 -0
- package/dist/src/overrides/TextInput.d.ts.map +1 -0
- package/dist/src/overrides/TextInput.js +213 -0
- package/dist/src/overrides/TextInput.js.map +1 -0
- package/dist/src/overrides/View.d.ts +36 -0
- package/dist/src/overrides/View.d.ts.map +1 -0
- package/dist/src/overrides/View.js +99 -0
- package/dist/src/overrides/View.js.map +1 -0
- package/dist/src/overrides/createPlatform.d.ts +32 -0
- package/dist/src/overrides/createPlatform.d.ts.map +1 -0
- package/dist/src/overrides/createPlatform.js +84 -0
- package/dist/src/overrides/createPlatform.js.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.js +84 -0
- package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
- package/dist/src/overrides/setUpXHR.d.ts +46 -0
- package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
- package/dist/src/overrides/setUpXHR.js +236 -0
- package/dist/src/overrides/setUpXHR.js.map +1 -0
- package/dist/src/quitRequest.d.ts +55 -0
- package/dist/src/quitRequest.d.ts.map +1 -0
- package/dist/src/quitRequest.js +121 -0
- package/dist/src/quitRequest.js.map +1 -0
- package/dist/src/resourcePath.d.ts +18 -0
- package/dist/src/resourcePath.d.ts.map +1 -0
- package/dist/src/resourcePath.js +31 -0
- package/dist/src/resourcePath.js.map +1 -0
- package/dist/src/responseBody.d.ts +76 -0
- package/dist/src/responseBody.d.ts.map +1 -0
- package/dist/src/responseBody.js +94 -0
- package/dist/src/responseBody.js.map +1 -0
- package/dist/src/responseHeaders.d.ts +40 -0
- package/dist/src/responseHeaders.d.ts.map +1 -0
- package/dist/src/responseHeaders.js +75 -0
- package/dist/src/responseHeaders.js.map +1 -0
- package/dist/src/titleBarState.d.ts +43 -0
- package/dist/src/titleBarState.d.ts.map +1 -0
- package/dist/src/titleBarState.js +77 -0
- package/dist/src/titleBarState.js.map +1 -0
- package/dist/src/useContextMenu.d.ts +113 -0
- package/dist/src/useContextMenu.d.ts.map +1 -0
- package/dist/src/useContextMenu.js +109 -0
- package/dist/src/useContextMenu.js.map +1 -0
- package/dist/src/useDialog.d.ts +98 -0
- package/dist/src/useDialog.d.ts.map +1 -0
- package/dist/src/useDialog.js +112 -0
- package/dist/src/useDialog.js.map +1 -0
- package/dist/src/useDisplays.d.ts +70 -0
- package/dist/src/useDisplays.d.ts.map +1 -0
- package/dist/src/useDisplays.js +118 -0
- package/dist/src/useDisplays.js.map +1 -0
- package/dist/src/useHandledKeys.d.ts +38 -0
- package/dist/src/useHandledKeys.d.ts.map +1 -0
- package/dist/src/useHandledKeys.js +70 -0
- package/dist/src/useHandledKeys.js.map +1 -0
- package/dist/src/useWindow.d.ts +140 -0
- package/dist/src/useWindow.d.ts.map +1 -0
- package/dist/src/useWindow.js +233 -0
- package/dist/src/useWindow.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/native/CMakeLists.txt +355 -0
- package/native/bootstrap.sh +613 -0
- package/native/cmake/CompilerFlags.cmake +49 -0
- package/native/cmake/Expo.cmake +125 -0
- package/native/cmake/ReactNativeCore.cmake +612 -0
- package/native/cmake/Reanimated.cmake +108 -0
- package/native/cmake/Skia.cmake +379 -0
- package/native/cmake/ThirdParty.cmake +290 -0
- package/native/cmake/Worklets.cmake +67 -0
- package/native/cmake/codegen/CMakeLists.txt +32 -0
- package/native/core/AppIdentity.cpp +85 -0
- package/native/core/AppIdentity.h +59 -0
- package/native/core/AppPaths.cpp +96 -0
- package/native/core/AppPaths.h +53 -0
- package/native/core/AppearanceModule.cpp +60 -0
- package/native/core/AppearanceModule.h +40 -0
- package/native/core/Backface.h +59 -0
- package/native/core/BlobModule.cpp +283 -0
- package/native/core/BlobModule.h +76 -0
- package/native/core/BlobRegistry.cpp +75 -0
- package/native/core/BlobRegistry.h +44 -0
- package/native/core/ColorScheme.cpp +105 -0
- package/native/core/ColorScheme.h +59 -0
- package/native/core/ComponentRegistry.h +30 -0
- package/native/core/ControlMetrics.h +37 -0
- package/native/core/CoreModules.cpp +592 -0
- package/native/core/CoreModules.h +308 -0
- package/native/core/DebuggingOverlay.cpp +106 -0
- package/native/core/DebuggingOverlay.h +65 -0
- package/native/core/DesktopControls.cpp +232 -0
- package/native/core/DesktopControls.h +170 -0
- package/native/core/DevBundle.cpp +108 -0
- package/native/core/DevBundle.h +69 -0
- package/native/core/DevMenu.cpp +99 -0
- package/native/core/DevMenu.h +75 -0
- package/native/core/DialogModule.cpp +150 -0
- package/native/core/DialogModule.h +51 -0
- package/native/core/DragAndDrop.cpp +45 -0
- package/native/core/DragAndDrop.h +225 -0
- package/native/core/ExpoImageComponent.cpp +79 -0
- package/native/core/ExpoImageComponent.h +80 -0
- package/native/core/ExpoModules.cpp +415 -0
- package/native/core/ExpoModules.h +115 -0
- package/native/core/ExpoRuntime.cpp +366 -0
- package/native/core/ExpoRuntime.h +42 -0
- package/native/core/FocusRing.h +36 -0
- package/native/core/FontRegistry.h +51 -0
- package/native/core/GestureHandlerModule.cpp +136 -0
- package/native/core/GestureHandlerModule.h +71 -0
- package/native/core/Gestures.cpp +533 -0
- package/native/core/Gestures.h +145 -0
- package/native/core/HoverTracker.cpp +69 -0
- package/native/core/HoverTracker.h +109 -0
- package/native/core/HttpClient.cpp +282 -0
- package/native/core/ImageBytes.cpp +205 -0
- package/native/core/ImageBytes.h +29 -0
- package/native/core/ImageCache.cpp +51 -0
- package/native/core/ImageCache.h +89 -0
- package/native/core/JsRuntimeAccess.cpp +70 -0
- package/native/core/JsRuntimeAccess.h +60 -0
- package/native/core/JsiPromise.h +51 -0
- package/native/core/KeyEvents.cpp +116 -0
- package/native/core/KeyEvents.h +144 -0
- package/native/core/LogBoxSurface.cpp +46 -0
- package/native/core/LogBoxSurface.h +68 -0
- package/native/core/MenuModel.h +117 -0
- package/native/core/MenuModule.cpp +209 -0
- package/native/core/MenuModule.h +66 -0
- package/native/core/MountingWalk.h +524 -0
- package/native/core/PackageModules.cpp.in +25 -0
- package/native/core/PackageModules.h +50 -0
- package/native/core/PlatformConstantsModule.cpp +63 -0
- package/native/core/PlatformConstantsModule.h +64 -0
- package/native/core/PlatformServices.h +213 -0
- package/native/core/PointerButtons.h +63 -0
- package/native/core/PullToRefresh.cpp +57 -0
- package/native/core/PullToRefresh.h +73 -0
- package/native/core/ReanimatedCompat.h +47 -0
- package/native/core/ReanimatedModule.cpp +203 -0
- package/native/core/ReanimatedModule.h +55 -0
- package/native/core/ScrollAnimation.cpp +59 -0
- package/native/core/ScrollAnimation.h +70 -0
- package/native/core/ScrollBounds.cpp +26 -0
- package/native/core/ScrollBounds.h +68 -0
- package/native/core/ScrollIndicator.cpp +50 -0
- package/native/core/ScrollIndicator.h +69 -0
- package/native/core/ScrollMomentum.cpp +71 -0
- package/native/core/ScrollMomentum.h +73 -0
- package/native/core/ScrollSnap.cpp +123 -0
- package/native/core/ScrollSnap.h +80 -0
- package/native/core/ShareFallback.cpp +101 -0
- package/native/core/ShareFallback.h +45 -0
- package/native/core/SkiaPictureViewComponent.cpp +11 -0
- package/native/core/SkiaPictureViewComponent.h +47 -0
- package/native/core/SourceCodeModule.cpp +55 -0
- package/native/core/SourceCodeModule.h +53 -0
- package/native/core/StatusBarModule.cpp +23 -0
- package/native/core/StatusBarModule.h +42 -0
- package/native/core/TestDialog.cpp +148 -0
- package/native/core/TestDialog.h +96 -0
- package/native/core/TestKeys.cpp +78 -0
- package/native/core/TestKeys.h +50 -0
- package/native/core/TestQuitFile.cpp +33 -0
- package/native/core/TestQuitFile.h +60 -0
- package/native/core/TestSettle.h +192 -0
- package/native/core/TitleBarRegions.h +31 -0
- package/native/core/TurboModuleProxy.cpp +51 -0
- package/native/core/TurboModuleProxy.h +46 -0
- package/native/core/UIManagerAccess.cpp +43 -0
- package/native/core/UIManagerAccess.h +43 -0
- package/native/core/WindowBoundsCache.cpp +319 -0
- package/native/core/WindowControl.h +235 -0
- package/native/core/WindowHost.h +158 -0
- package/native/core/WindowMethods.cpp +167 -0
- package/native/core/WindowMethods.h +84 -0
- package/native/core/WindowsModule.cpp +448 -0
- package/native/core/WindowsModule.h +133 -0
- package/native/core/WorkletsModule.cpp +199 -0
- package/native/core/WorkletsModule.h +57 -0
- package/native/core/portability_probe.cpp +210 -0
- package/native/tests/EventRecorder.h +124 -0
- package/native/tests/TestHarness.cpp +109 -0
- package/native/tests/TestHarness.h +89 -0
- package/native/tests/TreeDump.h +49 -0
- package/native/tests/test_app_identity.cpp +114 -0
- package/native/tests/test_app_paths.cpp +48 -0
- package/native/tests/test_appearance.cpp +107 -0
- package/native/tests/test_backface.cpp +79 -0
- package/native/tests/test_blobs.cpp +157 -0
- package/native/tests/test_controls.cpp +185 -0
- package/native/tests/test_devbundle.cpp +103 -0
- package/native/tests/test_drag_and_drop.cpp +143 -0
- package/native/tests/test_gestures.cpp +331 -0
- package/native/tests/test_hover.cpp +92 -0
- package/native/tests/test_image_cache.cpp +109 -0
- package/native/tests/test_js_runtime_access.cpp +137 -0
- package/native/tests/test_key_events.cpp +235 -0
- package/native/tests/test_momentum.cpp +138 -0
- package/native/tests/test_quit_file.cpp +104 -0
- package/native/tests/test_scroll_animation.cpp +120 -0
- package/native/tests/test_scroll_bounds.cpp +66 -0
- package/native/tests/test_scroll_indicator.cpp +149 -0
- package/native/tests/test_scroll_snap.cpp +112 -0
- package/native/tests/test_settle.cpp +115 -0
- package/native/tests/test_share.cpp +75 -0
- package/native/tests/test_sourcecode.cpp +62 -0
- package/native/tests/test_window_close.cpp +119 -0
- package/native/tests/test_window_limits.cpp +123 -0
- package/package.json +43 -0
- package/react-native.config.js +86 -0
- package/supported-versions.json +66 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#include "ExpoRuntime.h"
|
|
2
|
+
|
|
3
|
+
#include "ExpoModules.h"
|
|
4
|
+
#include "FontRegistry.h"
|
|
5
|
+
|
|
6
|
+
#include <filesystem>
|
|
7
|
+
#include <random>
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <string_view>
|
|
10
|
+
|
|
11
|
+
#ifdef BASALT_HAS_EXPO
|
|
12
|
+
#include <EventEmitter.h>
|
|
13
|
+
#include <JSI/JSIUtils.h>
|
|
14
|
+
#include <NativeModule.h>
|
|
15
|
+
#include <SharedObject.h>
|
|
16
|
+
#include <SharedRef.h>
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
namespace basalt {
|
|
20
|
+
|
|
21
|
+
bool hasExpoRuntime() {
|
|
22
|
+
#ifdef BASALT_HAS_EXPO
|
|
23
|
+
return true;
|
|
24
|
+
#else
|
|
25
|
+
return false;
|
|
26
|
+
#endif
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#ifdef BASALT_HAS_EXPO
|
|
30
|
+
|
|
31
|
+
namespace {
|
|
32
|
+
|
|
33
|
+
// A version 4 UUID: 122 random bits, with the version and variant fields set as
|
|
34
|
+
// RFC 4122 requires. `std::random_device` rather than a seeded generator --
|
|
35
|
+
// this names things that may outlive the process and must not repeat between
|
|
36
|
+
// two runs started in the same millisecond.
|
|
37
|
+
std::string randomUuidV4() {
|
|
38
|
+
std::random_device entropy;
|
|
39
|
+
std::uniform_int_distribution<unsigned> nibble(0, 15);
|
|
40
|
+
|
|
41
|
+
static constexpr char kHex[] = "0123456789abcdef";
|
|
42
|
+
std::string uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
|
|
43
|
+
for (char &c : uuid) {
|
|
44
|
+
if (c == 'x') {
|
|
45
|
+
c = kHex[nibble(entropy)];
|
|
46
|
+
} else if (c == 'y') {
|
|
47
|
+
// The variant: one of 8, 9, a or b.
|
|
48
|
+
c = kHex[(nibble(entropy) & 0x3U) | 0x8U];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return uuid;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
using facebook::jsi::Function;
|
|
55
|
+
using facebook::jsi::Object;
|
|
56
|
+
using facebook::jsi::PropNameID;
|
|
57
|
+
using facebook::jsi::Runtime;
|
|
58
|
+
using facebook::jsi::String;
|
|
59
|
+
using facebook::jsi::Value;
|
|
60
|
+
|
|
61
|
+
// An already-settled promise, which is all this module needs: registering a
|
|
62
|
+
// font is synchronous, and the JavaScript signature is async only because it is
|
|
63
|
+
// asynchronous everywhere else.
|
|
64
|
+
Value resolvedPromise(Runtime &rt) {
|
|
65
|
+
return rt.global()
|
|
66
|
+
.getPropertyAsObject(rt, "Promise")
|
|
67
|
+
.getPropertyAsFunction(rt, "resolve")
|
|
68
|
+
.call(rt);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Value rejectedPromise(Runtime &rt, const std::string &message) {
|
|
72
|
+
Function error = rt.global().getPropertyAsFunction(rt, "Error");
|
|
73
|
+
Value reason = error.callAsConstructor(rt, String::createFromUtf8(rt, message));
|
|
74
|
+
return rt.global()
|
|
75
|
+
.getPropertyAsObject(rt, "Promise")
|
|
76
|
+
.getPropertyAsFunction(rt, "reject")
|
|
77
|
+
.call(rt, reason);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// expo-font hands over whatever `expo-asset` resolved: a string, or an object
|
|
81
|
+
// with a localUri or uri. Both shapes appear depending on how the asset was
|
|
82
|
+
// bundled, so both are read rather than one being assumed.
|
|
83
|
+
std::string localPathFrom(Runtime &rt, const Value &resource) {
|
|
84
|
+
std::string uri;
|
|
85
|
+
if (resource.isString()) {
|
|
86
|
+
uri = resource.asString(rt).utf8(rt);
|
|
87
|
+
} else if (resource.isObject()) {
|
|
88
|
+
Object object = resource.asObject(rt);
|
|
89
|
+
for (const char *key : {"localUri", "uri"}) {
|
|
90
|
+
Value value = object.getProperty(rt, key);
|
|
91
|
+
if (value.isString()) {
|
|
92
|
+
uri = value.asString(rt).utf8(rt);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (uri.rfind("file://", 0) == 0) {
|
|
99
|
+
uri.erase(0, std::string_view{"file://"}.size());
|
|
100
|
+
}
|
|
101
|
+
return uri;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ExpoAsset, which is how expo-asset turns an asset's URL into a local file.
|
|
105
|
+
//
|
|
106
|
+
// For a `file://` URL there is nothing to download: React Native resolved it
|
|
107
|
+
// beside the bundle and it is already on disk, so the work is confirming that
|
|
108
|
+
// and handing the same URL back. The existence check is the point -- without it
|
|
109
|
+
// a missing asset succeeds here and fails much later, somewhere that has no
|
|
110
|
+
// idea which file was meant.
|
|
111
|
+
//
|
|
112
|
+
// An http URL is what a dev server produces, and fetching one is not
|
|
113
|
+
// implemented. It rejects saying so rather than pretending.
|
|
114
|
+
Object makeAssetModule(Runtime &runtime) {
|
|
115
|
+
Object module(runtime);
|
|
116
|
+
|
|
117
|
+
module.setProperty(
|
|
118
|
+
runtime,
|
|
119
|
+
"downloadAsync",
|
|
120
|
+
Function::createFromHostFunction(
|
|
121
|
+
runtime,
|
|
122
|
+
PropNameID::forAscii(runtime, "downloadAsync"),
|
|
123
|
+
3,
|
|
124
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
125
|
+
if (count < 1 || !args[0].isString()) {
|
|
126
|
+
return rejectedPromise(rt, "downloadAsync expects a url");
|
|
127
|
+
}
|
|
128
|
+
const std::string url = args[0].asString(rt).utf8(rt);
|
|
129
|
+
|
|
130
|
+
if (url.rfind("file://", 0) != 0) {
|
|
131
|
+
return rejectedPromise(
|
|
132
|
+
rt,
|
|
133
|
+
"basalt-core cannot fetch assets over the network yet; "
|
|
134
|
+
"got " + url);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const std::string path = url.substr(std::string_view{"file://"}.size());
|
|
138
|
+
std::error_code ignored;
|
|
139
|
+
if (!std::filesystem::is_regular_file(path, ignored)) {
|
|
140
|
+
return rejectedPromise(
|
|
141
|
+
rt,
|
|
142
|
+
"no asset at " + path +
|
|
143
|
+
". Assets are not copied beside the bundle yet.");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return rt.global()
|
|
147
|
+
.getPropertyAsObject(rt, "Promise")
|
|
148
|
+
.getPropertyAsFunction(rt, "resolve")
|
|
149
|
+
.call(rt, String::createFromUtf8(rt, url));
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
return module;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ExpoFontLoader, as far as a non-web platform is concerned. expo-font's own
|
|
156
|
+
// type declaration marks everything but these two as web-only.
|
|
157
|
+
Object makeFontLoader(Runtime &runtime) {
|
|
158
|
+
Object loader(runtime);
|
|
159
|
+
|
|
160
|
+
loader.setProperty(
|
|
161
|
+
runtime,
|
|
162
|
+
"loadAsync",
|
|
163
|
+
Function::createFromHostFunction(
|
|
164
|
+
runtime,
|
|
165
|
+
PropNameID::forAscii(runtime, "loadAsync"),
|
|
166
|
+
2,
|
|
167
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
168
|
+
if (count < 2 || !args[0].isString()) {
|
|
169
|
+
return rejectedPromise(rt, "loadAsync expects a family name and a font");
|
|
170
|
+
}
|
|
171
|
+
const std::string name = args[0].asString(rt).utf8(rt);
|
|
172
|
+
const std::string path = localPathFrom(rt, args[1]);
|
|
173
|
+
if (path.empty()) {
|
|
174
|
+
return rejectedPromise(
|
|
175
|
+
rt, "could not find a local file for font '" + name + "'");
|
|
176
|
+
}
|
|
177
|
+
if (!registerFont(name, path)) {
|
|
178
|
+
return rejectedPromise(rt, "could not load font '" + name + "' from " + path);
|
|
179
|
+
}
|
|
180
|
+
return resolvedPromise(rt);
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
loader.setProperty(
|
|
184
|
+
runtime,
|
|
185
|
+
"isLoaded",
|
|
186
|
+
Function::createFromHostFunction(
|
|
187
|
+
runtime,
|
|
188
|
+
PropNameID::forAscii(runtime, "isLoaded"),
|
|
189
|
+
1,
|
|
190
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
191
|
+
if (count < 1 || !args[0].isString()) {
|
|
192
|
+
return Value(false);
|
|
193
|
+
}
|
|
194
|
+
return Value(isFontRegistered(args[0].asString(rt).utf8(rt)));
|
|
195
|
+
}));
|
|
196
|
+
|
|
197
|
+
loader.setProperty(
|
|
198
|
+
runtime,
|
|
199
|
+
"getLoadedFonts",
|
|
200
|
+
Function::createFromHostFunction(
|
|
201
|
+
runtime,
|
|
202
|
+
PropNameID::forAscii(runtime, "getLoadedFonts"),
|
|
203
|
+
0,
|
|
204
|
+
[](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
205
|
+
Object array = rt.global()
|
|
206
|
+
.getPropertyAsFunction(rt, "Array")
|
|
207
|
+
.callAsConstructor(rt)
|
|
208
|
+
.asObject(rt);
|
|
209
|
+
Function push = array.getPropertyAsFunction(rt, "push");
|
|
210
|
+
|
|
211
|
+
const std::string joined = registeredFontNamesJoined('\n');
|
|
212
|
+
std::size_t start = 0;
|
|
213
|
+
while (start < joined.size()) {
|
|
214
|
+
const std::size_t end = joined.find('\n', start);
|
|
215
|
+
const std::string one =
|
|
216
|
+
joined.substr(start, end == std::string::npos ? std::string::npos : end - start);
|
|
217
|
+
push.callWithThis(rt, array, String::createFromUtf8(rt, one));
|
|
218
|
+
if (end == std::string::npos) {
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
start = end + 1;
|
|
222
|
+
}
|
|
223
|
+
return Value(rt, array);
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
return loader;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// `expo/fetch`, which this platform does not have, routed back to the one it
|
|
230
|
+
// does.
|
|
231
|
+
//
|
|
232
|
+
// Expo replaces `globalThis.fetch` with its own WinterCG implementation, built
|
|
233
|
+
// on a native module called `ExpoFetchModule` -- a pair of SharedObject classes
|
|
234
|
+
// with a streaming body between them. There is no port of it here, so the
|
|
235
|
+
// replacement is a lazy getter that throws `Cannot find native module
|
|
236
|
+
// 'ExpoFetchModule'` the first time anything in the app calls `fetch`. That is
|
|
237
|
+
// most apps, immediately, and it is not a failure an app can catch: it happens
|
|
238
|
+
// inside the global it was calling.
|
|
239
|
+
//
|
|
240
|
+
// Expo's own way out is `EXPO_PUBLIC_USE_RN_FETCH`, which leaves React Native's
|
|
241
|
+
// fetch in place -- and React Native's fetch works here, over the same curl
|
|
242
|
+
// client core/HttpClient.cpp gives the rest of the networking stack. So the
|
|
243
|
+
// default is set here rather than asked of every app, because "install basalt
|
|
244
|
+
// and the desktop works" stops being true if each app has to discover this
|
|
245
|
+
// variable from a crash inside `fetch`.
|
|
246
|
+
//
|
|
247
|
+
// **Before the bundle, so that everything downstream agrees.** Metro's prelude
|
|
248
|
+
// opens with `process = globalThis.process || {}` and React Native's
|
|
249
|
+
// setUpGlobals with `global.process = global.process || {}`, both of which keep
|
|
250
|
+
// what is already there. Expo's CLI then defines the app's own `EXPO_PUBLIC_`
|
|
251
|
+
// variables over the top in development, which is the right precedence: a
|
|
252
|
+
// developer who sets this explicitly beats the default. Plain assignment rather
|
|
253
|
+
// than defineProperty for that reason -- a non-configurable property here would
|
|
254
|
+
// make their `Object.defineProperties` throw.
|
|
255
|
+
//
|
|
256
|
+
// What is lost is what `expo/fetch` adds: a streamed response body. React
|
|
257
|
+
// Native's fetch buffers, and an app importing `expo/fetch` directly still gets
|
|
258
|
+
// the error naming the module, which is the honest answer until someone ports
|
|
259
|
+
// it.
|
|
260
|
+
void useReactNativeFetch(facebook::jsi::Runtime &runtime) {
|
|
261
|
+
namespace jsi = facebook::jsi;
|
|
262
|
+
static constexpr const char *kVariable = "EXPO_PUBLIC_USE_RN_FETCH";
|
|
263
|
+
|
|
264
|
+
jsi::Object global = runtime.global();
|
|
265
|
+
const jsi::Value processValue = global.getProperty(runtime, "process");
|
|
266
|
+
jsi::Object process =
|
|
267
|
+
processValue.isObject() ? processValue.asObject(runtime) : jsi::Object(runtime);
|
|
268
|
+
|
|
269
|
+
const jsi::Value envValue = process.getProperty(runtime, "env");
|
|
270
|
+
jsi::Object env = envValue.isObject() ? envValue.asObject(runtime) : jsi::Object(runtime);
|
|
271
|
+
|
|
272
|
+
// Only as a default. Nothing sets this before the bundle today, but something
|
|
273
|
+
// that did would have meant it.
|
|
274
|
+
if (env.getProperty(runtime, kVariable).isUndefined()) {
|
|
275
|
+
env.setProperty(runtime, kVariable, jsi::String::createFromAscii(runtime, "1"));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
process.setProperty(runtime, "env", std::move(env));
|
|
279
|
+
global.setProperty(runtime, "process", std::move(process));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
} // namespace
|
|
283
|
+
|
|
284
|
+
void installExpoRuntime(facebook::jsi::Runtime &runtime) {
|
|
285
|
+
namespace jsi = facebook::jsi;
|
|
286
|
+
|
|
287
|
+
// `expo` has to exist before the classes go in: each of them reaches for
|
|
288
|
+
// `global.expo` through expo::common::getCoreObject and hangs itself off it.
|
|
289
|
+
// Installing them first throws on a property that is not there yet.
|
|
290
|
+
runtime.global().setProperty(runtime, "expo", jsi::Object(runtime));
|
|
291
|
+
|
|
292
|
+
expo::EventEmitter::installClass(runtime);
|
|
293
|
+
|
|
294
|
+
// The releaser is how Expo hands a shared object's native half back to be
|
|
295
|
+
// freed. On Android it reaches through JNI to the owning context. Nothing
|
|
296
|
+
// here owns any native Expo object -- no Expo module is ported yet -- so
|
|
297
|
+
// there is nothing to free, and the honest implementation of "free nothing"
|
|
298
|
+
// is to do nothing.
|
|
299
|
+
expo::SharedObject::installBaseClass(runtime, [](expo::SharedObject::ObjectId) {});
|
|
300
|
+
expo::SharedRef::installBaseClass(runtime);
|
|
301
|
+
expo::NativeModule::installClass(runtime);
|
|
302
|
+
|
|
303
|
+
// The module registry.
|
|
304
|
+
//
|
|
305
|
+
// ExpoAsset is here rather than in ExpoModules.cpp because it is older than
|
|
306
|
+
// the module host and because it is half a stub: it confirms a `file://`
|
|
307
|
+
// asset exists and rejects an http one, which is enough for Expo's own
|
|
308
|
+
// start-up and no more. ExponentConstants used to sit beside it as an empty
|
|
309
|
+
// object for the same reason, and is a real module now.
|
|
310
|
+
jsi::Object modules(runtime);
|
|
311
|
+
modules.setProperty(runtime, "ExpoAsset", makeAssetModule(runtime));
|
|
312
|
+
|
|
313
|
+
// The first Expo module here that is not a stub. It loads a real font file
|
|
314
|
+
// into fontconfig, which is where Pango looks, so `fontFamily` works
|
|
315
|
+
// afterwards for text this platform renders. See src/LinuxFonts.cpp.
|
|
316
|
+
modules.setProperty(runtime, "ExpoFontLoader", makeFontLoader(runtime));
|
|
317
|
+
|
|
318
|
+
// This platform's own Expo modules. See core/ExpoModules.h; they are separate
|
|
319
|
+
// from the stubs above because they are not stubs.
|
|
320
|
+
installExpoModules(runtime, modules);
|
|
321
|
+
|
|
322
|
+
// expo-modules-core builds its NativeModulesProxy by iterating this, falling
|
|
323
|
+
// back to the legacy proxy when it is absent, so its presence matters even
|
|
324
|
+
// when it is empty.
|
|
325
|
+
jsi::Object proxy(runtime);
|
|
326
|
+
proxy.setProperty(runtime, "exportedMethods", jsi::Object(runtime));
|
|
327
|
+
proxy.setProperty(runtime, "viewManagersMetadata", jsi::Object(runtime));
|
|
328
|
+
modules.setProperty(runtime, "NativeModulesProxy", std::move(proxy));
|
|
329
|
+
|
|
330
|
+
jsi::Object core = runtime.global().getPropertyAsObject(runtime, "expo");
|
|
331
|
+
core.setProperty(runtime, "modules", std::move(modules));
|
|
332
|
+
installExpoViewConfigs(runtime, core);
|
|
333
|
+
|
|
334
|
+
// Before the bundle evaluates, which is the only moment early enough; see the
|
|
335
|
+
// function.
|
|
336
|
+
useReactNativeFetch(runtime);
|
|
337
|
+
|
|
338
|
+
// `expo.uuidv4`, which expo-modules-core's own `uuid.v4()` calls and throws
|
|
339
|
+
// without: "Native UUID version 4 generator implementation wasn't found in
|
|
340
|
+
// `expo-modules-core`". It is not a notifications concern, though that is
|
|
341
|
+
// where it was found -- `scheduleNotificationAsync` names a notification with
|
|
342
|
+
// one when an app does not, and so does every other Expo package that
|
|
343
|
+
// generates an identifier.
|
|
344
|
+
//
|
|
345
|
+
// `uuidv5` is deliberately absent: it is a SHA-1 of a namespace and a name,
|
|
346
|
+
// which is a hash implementation rather than a random number, and expo
|
|
347
|
+
// reports a missing one by name the way it reports a missing method.
|
|
348
|
+
core.setProperty(
|
|
349
|
+
runtime,
|
|
350
|
+
"uuidv4",
|
|
351
|
+
jsi::Function::createFromHostFunction(
|
|
352
|
+
runtime,
|
|
353
|
+
jsi::PropNameID::forAscii(runtime, "uuidv4"),
|
|
354
|
+
0,
|
|
355
|
+
[](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
356
|
+
return jsi::String::createFromUtf8(rt, randomUuidV4());
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
#else
|
|
361
|
+
|
|
362
|
+
void installExpoRuntime(facebook::jsi::Runtime & /*runtime*/) {}
|
|
363
|
+
|
|
364
|
+
#endif
|
|
365
|
+
|
|
366
|
+
} // namespace basalt
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Expo's runtime, installed into the JavaScript runtime before the bundle runs.
|
|
2
|
+
//
|
|
3
|
+
// An Expo app's very first import reaches `globalThis.expo.EventEmitter`, and
|
|
4
|
+
// without it the app dies before React renders. That object is normally
|
|
5
|
+
// installed from native code, which is why an Expo app cannot start on a
|
|
6
|
+
// platform nobody has ported Expo to.
|
|
7
|
+
//
|
|
8
|
+
// The port is smaller than it sounds, because expo-modules-core ships the
|
|
9
|
+
// portable half in its npm package: `common/cpp` holds EventEmitter,
|
|
10
|
+
// SharedObject, SharedRef, NativeModule and their JSI helpers, and depends on
|
|
11
|
+
// nothing but JSI and a call invoker. So there is nothing to vendor and nothing
|
|
12
|
+
// to fetch -- this compiles the app's own copy, at the app's own version, the
|
|
13
|
+
// same arrangement that keeps React Native's C++ and JavaScript in step.
|
|
14
|
+
//
|
|
15
|
+
// react-native-windows and react-native-macos reach the same place by way of
|
|
16
|
+
// shirakaba/expo-desktop, which vendors that directory at a pinned Expo SDK.
|
|
17
|
+
// Compiling the app's copy avoids the pin.
|
|
18
|
+
//
|
|
19
|
+
// What this installs is deliberately the floor rather than the ceiling: the
|
|
20
|
+
// four classes and an empty module registry, which is what an Expo app needs to
|
|
21
|
+
// *start*. Any actual Expo module -- expo-font, expo-image, a config plugin's
|
|
22
|
+
// native half -- needs its own port, and this does not pretend otherwise.
|
|
23
|
+
|
|
24
|
+
#pragma once
|
|
25
|
+
|
|
26
|
+
#include <jsi/jsi.h>
|
|
27
|
+
|
|
28
|
+
namespace basalt {
|
|
29
|
+
|
|
30
|
+
// Installs `globalThis.expo`. Call before the bundle is evaluated; ReactHost's
|
|
31
|
+
// bindingsInstallFunc is that moment.
|
|
32
|
+
//
|
|
33
|
+
// Compiled only when the build was pointed at an expo-modules-core; without one
|
|
34
|
+
// this is a no-op, so a plain React Native app pays nothing and an Expo app
|
|
35
|
+
// fails the way it did before rather than differently.
|
|
36
|
+
void installExpoRuntime(facebook::jsi::Runtime &runtime);
|
|
37
|
+
|
|
38
|
+
// Whether the above will do anything, for the log line that tells a developer
|
|
39
|
+
// which of the two situations they are in.
|
|
40
|
+
bool hasExpoRuntime();
|
|
41
|
+
|
|
42
|
+
} // namespace basalt
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// What keyboard focus looks like.
|
|
2
|
+
//
|
|
3
|
+
// Two numbers and a colour, in one place, for the same reason
|
|
4
|
+
// `kWheelStepPixels` is: a ring that is two pixels of blue on one desktop and
|
|
5
|
+
// three of grey on another is a difference an app did not ask for and cannot
|
|
6
|
+
// control. Matching the other platform matters more here than matching either
|
|
7
|
+
// toolkit's own default, which is the argument of this project in one constant.
|
|
8
|
+
//
|
|
9
|
+
// Not the system accent colour, on either desktop, and that is a real choice
|
|
10
|
+
// rather than an omission. macOS has `NSColor.keyboardFocusIndicatorColor` and
|
|
11
|
+
// GTK has a theme; using each would make the ring native and make the two
|
|
12
|
+
// desktops disagree, and an app that draws its own buttons in its own colours
|
|
13
|
+
// has already said it is not trying to look native. The same reasoning kept
|
|
14
|
+
// `<TextInput>`'s peers looking like the app rather than like the toolkit.
|
|
15
|
+
//
|
|
16
|
+
// Drawn rather than delegated for a second reason too: these widgets have no
|
|
17
|
+
// theme to delegate to. React Native decided every colour in the tree, and GTK's
|
|
18
|
+
// focus rendering is a CSS outline on a themed widget.
|
|
19
|
+
|
|
20
|
+
#pragma once
|
|
21
|
+
|
|
22
|
+
namespace basalt {
|
|
23
|
+
|
|
24
|
+
// Pixels, outside the view's own bounds, so the ring does not cover content at
|
|
25
|
+
// the edge of a button.
|
|
26
|
+
constexpr float kFocusRingWidth = 2.0F;
|
|
27
|
+
|
|
28
|
+
// A blue that reads as "focused" on a light background and on a dark one, which
|
|
29
|
+
// is what an app-coloured tree offers no guarantees about. sRGB, 0..1 per
|
|
30
|
+
// channel, in the order every host's colour type takes.
|
|
31
|
+
constexpr float kFocusRingRed = 0.259F;
|
|
32
|
+
constexpr float kFocusRingGreen = 0.522F;
|
|
33
|
+
constexpr float kFocusRingBlue = 0.957F;
|
|
34
|
+
constexpr float kFocusRingAlpha = 1.0F;
|
|
35
|
+
|
|
36
|
+
} // namespace basalt
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Fonts an app loads at runtime, and the name it knows them by.
|
|
2
|
+
//
|
|
3
|
+
// Declared here and implemented per platform, because this is one of the places
|
|
4
|
+
// a desktop platform genuinely differs: fontconfig on Linux, and something else
|
|
5
|
+
// on macOS or Windows. Core calls it -- `expo-font` arrives here -- and links
|
|
6
|
+
// against whichever implementation the platform half provides. Linux's is
|
|
7
|
+
// src/FontRegistryFontconfig.cpp.
|
|
8
|
+
//
|
|
9
|
+
// `expo-font` hands over a file and a name of the app's choosing -- "Inter",
|
|
10
|
+
// say -- and expects `fontFamily: 'Inter'` to work afterwards. A font file
|
|
11
|
+
// carries its own family name inside it, which is usually something else
|
|
12
|
+
// entirely, and fontconfig indexes by that. So loading the file is only half
|
|
13
|
+
// the job; the other half is remembering that this app calls it "Inter".
|
|
14
|
+
//
|
|
15
|
+
// Kept here rather than in the Expo layer because the Pango side has to consult
|
|
16
|
+
// it on every text measurement, and because nothing about it is Expo-specific:
|
|
17
|
+
// any future API that loads a font at runtime wants exactly this.
|
|
18
|
+
|
|
19
|
+
#pragma once
|
|
20
|
+
|
|
21
|
+
#include <string>
|
|
22
|
+
|
|
23
|
+
namespace basalt {
|
|
24
|
+
|
|
25
|
+
// Makes a font file available to Pango, under `name`.
|
|
26
|
+
//
|
|
27
|
+
// Returns false if the file cannot be read or fontconfig will not take it, in
|
|
28
|
+
// which case nothing is registered. Safe to call twice with the same name.
|
|
29
|
+
bool registerFont(const std::string &name, const std::string &path);
|
|
30
|
+
|
|
31
|
+
// The family Pango should be asked for, given what the app called it. Returns
|
|
32
|
+
// `name` unchanged when it was never registered, so ordinary system families
|
|
33
|
+
// pass straight through.
|
|
34
|
+
std::string resolveFontFamily(const std::string &name);
|
|
35
|
+
|
|
36
|
+
// Bumped every time a font is registered. Text measured before a font arrived
|
|
37
|
+
// was measured against a different set of fonts, and a cache that does not know
|
|
38
|
+
// that will keep handing back the old size -- which is what makes a font loaded
|
|
39
|
+
// after first render appear to do nothing.
|
|
40
|
+
unsigned long fontGeneration();
|
|
41
|
+
|
|
42
|
+
// Whether `name` has been registered. expo-font insists this exists and is a
|
|
43
|
+
// function, and throws when it is not, so it is not optional however web-only
|
|
44
|
+
// its type declaration claims to be.
|
|
45
|
+
bool isFontRegistered(const std::string &name);
|
|
46
|
+
|
|
47
|
+
// The names registered so far, in registration order, for
|
|
48
|
+
// ExpoFontLoader.getLoadedFonts.
|
|
49
|
+
std::string registeredFontNamesJoined(char separator);
|
|
50
|
+
|
|
51
|
+
} // namespace basalt
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#include "GestureHandlerModule.h"
|
|
2
|
+
|
|
3
|
+
#include "Gestures.h"
|
|
4
|
+
#include "PlatformServices.h"
|
|
5
|
+
|
|
6
|
+
#include <jsi/JSIDynamic.h>
|
|
7
|
+
|
|
8
|
+
namespace basalt {
|
|
9
|
+
|
|
10
|
+
using facebook::jsi::Runtime;
|
|
11
|
+
using facebook::jsi::Value;
|
|
12
|
+
using facebook::react::TurboModule;
|
|
13
|
+
|
|
14
|
+
namespace {
|
|
15
|
+
|
|
16
|
+
double numberArg(const Value *args, size_t count, size_t index) {
|
|
17
|
+
return index < count && args[index].isNumber() ? args[index].asNumber() : 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
folly::dynamic objectArg(Runtime &runtime, const Value *args, size_t count, size_t index) {
|
|
21
|
+
if (index >= count || !args[index].isObject()) {
|
|
22
|
+
return folly::dynamic::object();
|
|
23
|
+
}
|
|
24
|
+
return facebook::jsi::dynamicFromValue(runtime, args[index]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
} // namespace
|
|
28
|
+
|
|
29
|
+
DesktopGestureHandlerModule::DesktopGestureHandlerModule(
|
|
30
|
+
std::shared_ptr<facebook::react::CallInvoker> jsInvoker)
|
|
31
|
+
: TurboModule(kModuleName, std::move(jsInvoker)) {
|
|
32
|
+
methodMap_["createGestureHandler"] = MethodMetadata{3, createGestureHandler};
|
|
33
|
+
methodMap_["attachGestureHandler"] = MethodMetadata{3, attachGestureHandler};
|
|
34
|
+
methodMap_["updateGestureHandler"] = MethodMetadata{2, updateGestureHandler};
|
|
35
|
+
methodMap_["dropGestureHandler"] = MethodMetadata{1, dropGestureHandler};
|
|
36
|
+
methodMap_["install"] = MethodMetadata{0, install};
|
|
37
|
+
// Nothing here batches, so there is nothing to flush; and there is no
|
|
38
|
+
// responder to hand over, because this platform's gesture recognisers and
|
|
39
|
+
// React Native's touches are fed from the same place rather than competing
|
|
40
|
+
// for a responder. See core/Gestures.h.
|
|
41
|
+
methodMap_["flushOperations"] = MethodMetadata{0, noop};
|
|
42
|
+
methodMap_["handleSetJSResponder"] = MethodMetadata{2, noop};
|
|
43
|
+
methodMap_["handleClearJSResponder"] = MethodMetadata{0, noop};
|
|
44
|
+
|
|
45
|
+
// The registry outlives any one instance of this module -- it is UI-thread
|
|
46
|
+
// state and the module is recreated whenever the runtime is -- so the
|
|
47
|
+
// emitter is installed here and taken away in the destructor rather than
|
|
48
|
+
// left pointing at a module that has gone.
|
|
49
|
+
gestures().setEmitter([this](const std::string &eventName, folly::dynamic payload) {
|
|
50
|
+
emitGestureEvent(eventName, std::move(payload));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
DesktopGestureHandlerModule::~DesktopGestureHandlerModule() {
|
|
55
|
+
gestures().setEmitter(nullptr);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void DesktopGestureHandlerModule::emitGestureEvent(const std::string &eventName,
|
|
59
|
+
folly::dynamic payload) {
|
|
60
|
+
emitDeviceEvent(eventName,
|
|
61
|
+
[payload = std::move(payload)](Runtime &runtime, std::vector<Value> &args) {
|
|
62
|
+
args.emplace_back(facebook::jsi::valueFromDynamic(runtime, payload));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Value DesktopGestureHandlerModule::createGestureHandler(Runtime &runtime,
|
|
67
|
+
TurboModule & /*module*/,
|
|
68
|
+
const Value *args,
|
|
69
|
+
size_t count) {
|
|
70
|
+
if (count < 2 || !args[0].isString()) {
|
|
71
|
+
return Value::undefined();
|
|
72
|
+
}
|
|
73
|
+
std::string name = args[0].asString(runtime).utf8(runtime);
|
|
74
|
+
const int tag = static_cast<int>(numberArg(args, count, 1));
|
|
75
|
+
folly::dynamic config = objectArg(runtime, args, count, 2);
|
|
76
|
+
|
|
77
|
+
postToUiThread([name = std::move(name), tag, config = std::move(config)]() mutable {
|
|
78
|
+
gestures().create(name, tag, std::move(config));
|
|
79
|
+
});
|
|
80
|
+
return Value::undefined();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Value DesktopGestureHandlerModule::attachGestureHandler(Runtime & /*runtime*/,
|
|
84
|
+
TurboModule & /*module*/,
|
|
85
|
+
const Value *args,
|
|
86
|
+
size_t count) {
|
|
87
|
+
const int handlerTag = static_cast<int>(numberArg(args, count, 0));
|
|
88
|
+
const int viewTag = static_cast<int>(numberArg(args, count, 1));
|
|
89
|
+
// The third argument is RNGH's ActionType. 1 is REANIMATED_WORKLET, which
|
|
90
|
+
// means the callbacks are worklets and the events are meant for a worklet
|
|
91
|
+
// runtime rather than for DeviceEventEmitter. Attaching it anyway is right:
|
|
92
|
+
// the handler still runs, and its events are still emitted; what a worklet
|
|
93
|
+
// gesture loses is being handled off the JS thread.
|
|
94
|
+
postToUiThread([handlerTag, viewTag]() { gestures().attach(handlerTag, viewTag); });
|
|
95
|
+
return Value::undefined();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Value DesktopGestureHandlerModule::updateGestureHandler(Runtime &runtime,
|
|
99
|
+
TurboModule & /*module*/,
|
|
100
|
+
const Value *args,
|
|
101
|
+
size_t count) {
|
|
102
|
+
const int handlerTag = static_cast<int>(numberArg(args, count, 0));
|
|
103
|
+
folly::dynamic config = objectArg(runtime, args, count, 1);
|
|
104
|
+
postToUiThread([handlerTag, config = std::move(config)]() mutable {
|
|
105
|
+
gestures().update(handlerTag, std::move(config));
|
|
106
|
+
});
|
|
107
|
+
return Value::undefined();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
Value DesktopGestureHandlerModule::dropGestureHandler(Runtime & /*runtime*/,
|
|
111
|
+
TurboModule & /*module*/,
|
|
112
|
+
const Value *args,
|
|
113
|
+
size_t count) {
|
|
114
|
+
const int handlerTag = static_cast<int>(numberArg(args, count, 0));
|
|
115
|
+
postToUiThread([handlerTag]() { gestures().drop(handlerTag); });
|
|
116
|
+
return Value::undefined();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// True means "the JSI bindings are in place". RNGH calls this once, on the
|
|
120
|
+
// first render of a GestureHandlerRootView under Fabric, and uses the answer
|
|
121
|
+
// only to avoid calling it again.
|
|
122
|
+
Value DesktopGestureHandlerModule::install(Runtime & /*runtime*/,
|
|
123
|
+
TurboModule & /*module*/,
|
|
124
|
+
const Value * /*args*/,
|
|
125
|
+
size_t /*count*/) {
|
|
126
|
+
return Value(true);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Value DesktopGestureHandlerModule::noop(Runtime & /*runtime*/,
|
|
130
|
+
TurboModule & /*module*/,
|
|
131
|
+
const Value * /*args*/,
|
|
132
|
+
size_t /*count*/) {
|
|
133
|
+
return Value::undefined();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
} // namespace basalt
|