react-native-image-stitcher 0.14.2 → 0.15.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/CHANGELOG.md +131 -0
- package/README.md +35 -0
- package/RNImageStitcher.podspec +8 -7
- package/android/build.gradle +0 -16
- package/android/src/main/cpp/CMakeLists.txt +2 -63
- package/android/src/main/cpp/image_stitcher_jni.cpp +14 -0
- package/android/src/main/cpp/keyframe_gate_jni.cpp +13 -0
- package/android/src/main/java/io/imagestitcher/rn/BatchStitcher.kt +285 -3
- package/android/src/main/java/io/imagestitcher/rn/IncrementalStitcher.kt +180 -1162
- package/android/src/main/java/io/imagestitcher/rn/KeyframeGate.kt +29 -0
- package/android/src/main/java/io/imagestitcher/rn/RNImageStitcherPackage.kt +0 -4
- package/android/src/main/java/io/imagestitcher/rn/RNSARCameraView.kt +13 -64
- package/cpp/keyframe_gate.cpp +82 -23
- package/cpp/keyframe_gate.hpp +31 -2
- package/cpp/stitcher.cpp +208 -28
- package/cpp/tests/CMakeLists.txt +18 -12
- package/cpp/tests/keyframe_timebudget_test.cpp +65 -0
- package/cpp/tests/warp_guard_test.cpp +48 -0
- package/cpp/warp_guard.hpp +41 -0
- package/dist/camera/Camera.d.ts +31 -16
- package/dist/camera/Camera.js +10 -2
- package/dist/camera/CaptureStitchStatsToast.d.ts +15 -2
- package/dist/camera/CaptureStitchStatsToast.js +27 -7
- package/dist/camera/PanoramaSettings.d.ts +10 -223
- package/dist/camera/PanoramaSettings.js +6 -28
- package/dist/camera/PanoramaSettingsBridge.d.ts +1 -24
- package/dist/camera/PanoramaSettingsBridge.js +3 -102
- package/dist/camera/PanoramaSettingsModal.js +7 -1
- package/dist/camera/buildPanoramaInitialSettings.d.ts +11 -0
- package/dist/camera/buildPanoramaInitialSettings.js +4 -0
- package/dist/camera/cameraErrorMessages.d.ts +32 -0
- package/dist/camera/cameraErrorMessages.js +53 -0
- package/dist/camera/selectCaptureDevice.d.ts +5 -1
- package/dist/camera/selectCaptureDevice.js +22 -2
- package/dist/camera/useCapture.js +38 -0
- package/dist/index.d.ts +5 -8
- package/dist/index.js +11 -34
- package/dist/stitching/incremental.d.ts +1 -117
- package/dist/stitching/stitchVideo.d.ts +0 -35
- package/dist/types.d.ts +0 -87
- package/ios/Sources/RNImageStitcher/IncrementalStitcher.swift +96 -674
- package/ios/Sources/RNImageStitcher/IncrementalStitcherBridge.swift +9 -12
- package/ios/Sources/RNImageStitcher/KeyframeGate.swift +14 -0
- package/ios/Sources/RNImageStitcher/KeyframeGateBridge.h +7 -0
- package/ios/Sources/RNImageStitcher/KeyframeGateBridge.mm +6 -0
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.h +2 -2
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.mm +3 -3
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.h +28 -60
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.mm +180 -921
- package/ios/Sources/RNImageStitcher/RNSARSession.swift +10 -35
- package/ios/Sources/RNImageStitcher/Stitcher.swift +84 -35
- package/ios/Sources/RNImageStitcher/StitcherBridge.m +13 -0
- package/ios/Sources/RNImageStitcher/StitcherBridge.swift +132 -5
- package/package.json +3 -2
- package/src/camera/Camera.tsx +43 -22
- package/src/camera/CaptureStitchStatsToast.tsx +58 -14
- package/src/camera/PanoramaSettings.ts +16 -289
- package/src/camera/PanoramaSettingsBridge.ts +3 -114
- package/src/camera/PanoramaSettingsModal.tsx +14 -1
- package/src/camera/__tests__/PanoramaSettingsBridge.test.ts +3 -188
- package/src/camera/__tests__/buildPanoramaInitialSettings.test.ts +41 -0
- package/src/camera/__tests__/cameraErrorMessages.test.ts +76 -0
- package/src/camera/__tests__/selectCaptureDevice.test.ts +33 -0
- package/src/camera/buildPanoramaInitialSettings.ts +17 -0
- package/src/camera/cameraErrorMessages.ts +84 -0
- package/src/camera/selectCaptureDevice.ts +28 -3
- package/src/camera/useCapture.ts +44 -1
- package/src/index.ts +11 -40
- package/src/stitching/incremental.ts +3 -140
- package/src/stitching/stitchVideo.ts +0 -26
- package/src/types.ts +0 -95
- package/android/src/main/cpp/stitcher_jsi_install_jni.cpp +0 -227
- package/android/src/main/java/io/imagestitcher/rn/IncrementalFirstwinsEngine.kt +0 -1081
- package/android/src/main/java/io/imagestitcher/rn/StitcherJsiInstallerModule.kt +0 -103
- package/android/src/main/java/io/imagestitcher/rn/StitcherWorkletRuntime.kt +0 -256
- package/cpp/stitcher_frame_jsi.cpp +0 -214
- package/cpp/stitcher_frame_jsi.hpp +0 -108
- package/cpp/stitcher_proxy_jsi.cpp +0 -109
- package/cpp/stitcher_proxy_jsi.hpp +0 -46
- package/cpp/stitcher_worklet_dispatch.cpp +0 -103
- package/cpp/stitcher_worklet_dispatch.hpp +0 -71
- package/cpp/stitcher_worklet_registry.cpp +0 -91
- package/cpp/stitcher_worklet_registry.hpp +0 -146
- package/cpp/tests/stitcher_worklet_registry_test.cpp +0 -195
- package/dist/stitching/IncrementalStitcherView.d.ts +0 -41
- package/dist/stitching/IncrementalStitcherView.js +0 -157
- package/dist/stitching/StitcherWorkletRegistry.d.ts +0 -117
- package/dist/stitching/StitcherWorkletRegistry.js +0 -78
- package/dist/stitching/ensureStitcherProxyInstalled.d.ts +0 -8
- package/dist/stitching/ensureStitcherProxyInstalled.js +0 -81
- package/dist/stitching/useFrameProcessor.d.ts +0 -119
- package/dist/stitching/useFrameProcessor.js +0 -196
- package/dist/stitching/useFrameStream.d.ts +0 -34
- package/dist/stitching/useFrameStream.js +0 -234
- package/dist/stitching/useThrottledFrameProcessor.d.ts +0 -33
- package/dist/stitching/useThrottledFrameProcessor.js +0 -132
- package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.h +0 -474
- package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.mm +0 -1328
- package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.h +0 -103
- package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.mm +0 -3285
- package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.h +0 -128
- package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.mm +0 -313
- package/ios/Sources/RNImageStitcher/SaveFrameAsJpegPlugin.mm +0 -185
- package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.h +0 -60
- package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.mm +0 -214
- package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.h +0 -42
- package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.mm +0 -160
- package/src/stitching/IncrementalStitcherView.tsx +0 -198
- package/src/stitching/StitcherWorkletRegistry.ts +0 -156
- package/src/stitching/__tests__/StitcherWorkletRegistry.test.ts +0 -176
- package/src/stitching/__tests__/ensureStitcherProxyInstalled.test.ts +0 -94
- package/src/stitching/__tests__/useThrottledFrameProcessor.test.ts +0 -178
- package/src/stitching/ensureStitcherProxyInstalled.ts +0 -141
- package/src/stitching/useFrameProcessor.ts +0 -226
- package/src/stitching/useFrameStream.ts +0 -271
- package/src/stitching/useThrottledFrameProcessor.ts +0 -145
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// stitcher_worklet_registry_test.cpp — v0.10.0 audit #9A
|
|
4
|
-
//
|
|
5
|
-
// Lifecycle + concurrency coverage for the process-scope native
|
|
6
|
-
// `StitcherWorkletRegistry` introduced in v0.8.0 Phase 4b. See
|
|
7
|
-
// `cpp/stitcher_worklet_registry.hpp` for the public contract.
|
|
8
|
-
//
|
|
9
|
-
// The registry's production `install(runtime, workletValue)` path
|
|
10
|
-
// constructs an `RNWorklet::WorkletInvoker` from a JSI `Runtime` and
|
|
11
|
-
// `Value`. Standing up a real worklets-core runtime under gtest would
|
|
12
|
-
// pull in Hermes + JSI + the whole worklets-core library — too heavy
|
|
13
|
-
// for these scope-limited storage tests. Instead we exercise the
|
|
14
|
-
// equivalent `_installEntryForTests(invoker)` test seam (mirrors
|
|
15
|
-
// `_resetForTests` in pattern) with `nullptr` invokers. The registry
|
|
16
|
-
// never dereferences the pointer — it only stores the shared_ptr and
|
|
17
|
-
// hands it back via `snapshot` — so nullptr is safe.
|
|
18
|
-
//
|
|
19
|
-
// What this covers (lifting from the production `install`/`uninstall`/
|
|
20
|
-
// `snapshot`/`count` contract):
|
|
21
|
-
// - shared() returns the same instance across calls
|
|
22
|
-
// - count/snapshot start empty after _resetForTests
|
|
23
|
-
// - install assigns monotonically increasing host-N IDs
|
|
24
|
-
// - count tracks installs / uninstalls
|
|
25
|
-
// - uninstall of an unknown ID is a no-op (matches JS side)
|
|
26
|
-
// - snapshot returns an independent copy (mutations after snapshot
|
|
27
|
-
// don't affect the snapshot's view)
|
|
28
|
-
// - concurrent installs from many threads serialise correctly and
|
|
29
|
-
// yield unique IDs (no double-issue under contention)
|
|
30
|
-
|
|
31
|
-
#include "stitcher_worklet_registry.hpp"
|
|
32
|
-
#include <react-native-worklets-core/WKTJsiWorklet.h>
|
|
33
|
-
|
|
34
|
-
#include <gtest/gtest.h>
|
|
35
|
-
|
|
36
|
-
#include <algorithm>
|
|
37
|
-
#include <atomic>
|
|
38
|
-
#include <chrono>
|
|
39
|
-
#include <set>
|
|
40
|
-
#include <string>
|
|
41
|
-
#include <thread>
|
|
42
|
-
#include <vector>
|
|
43
|
-
|
|
44
|
-
using retailens::StitcherWorkletEntry;
|
|
45
|
-
using retailens::StitcherWorkletRegistry;
|
|
46
|
-
|
|
47
|
-
namespace {
|
|
48
|
-
|
|
49
|
-
/// Test fixture — resets the singleton before each test so cases
|
|
50
|
-
/// don't leak state into each other. Without this every test would
|
|
51
|
-
/// see the cumulative entries from prior tests in the run.
|
|
52
|
-
class StitcherWorkletRegistryTest : public ::testing::Test {
|
|
53
|
-
protected:
|
|
54
|
-
void SetUp() override {
|
|
55
|
-
StitcherWorkletRegistry::shared()._resetForTests();
|
|
56
|
-
}
|
|
57
|
-
void TearDown() override {
|
|
58
|
-
StitcherWorkletRegistry::shared()._resetForTests();
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
} // namespace
|
|
63
|
-
|
|
64
|
-
TEST_F(StitcherWorkletRegistryTest, SharedReturnsSameInstance) {
|
|
65
|
-
// The singleton invariant is load-bearing for the JS-side mental
|
|
66
|
-
// model: `useFrameProcessor` mounts on one component and unmounts
|
|
67
|
-
// from another but the registry stays.
|
|
68
|
-
StitcherWorkletRegistry& a = StitcherWorkletRegistry::shared();
|
|
69
|
-
StitcherWorkletRegistry& b = StitcherWorkletRegistry::shared();
|
|
70
|
-
EXPECT_EQ(&a, &b);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
TEST_F(StitcherWorkletRegistryTest, StartsEmptyAfterReset) {
|
|
74
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
75
|
-
EXPECT_EQ(r.count(), 0u);
|
|
76
|
-
EXPECT_TRUE(r.snapshot().empty());
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
TEST_F(StitcherWorkletRegistryTest, InstallAssignsHostPrefixedIncrementingIds) {
|
|
80
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
81
|
-
const std::string id0 = r._installEntryForTests(nullptr);
|
|
82
|
-
const std::string id1 = r._installEntryForTests(nullptr);
|
|
83
|
-
const std::string id2 = r._installEntryForTests(nullptr);
|
|
84
|
-
|
|
85
|
-
// IDs are "host-N" with N monotonically increasing from 0 after a
|
|
86
|
-
// reset. The format is part of the public contract — uninstall
|
|
87
|
-
// callers store these IDs verbatim.
|
|
88
|
-
EXPECT_EQ(id0, "host-0");
|
|
89
|
-
EXPECT_EQ(id1, "host-1");
|
|
90
|
-
EXPECT_EQ(id2, "host-2");
|
|
91
|
-
EXPECT_EQ(r.count(), 3u);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
TEST_F(StitcherWorkletRegistryTest, UninstallRemovesByIdAndUpdatesCount) {
|
|
95
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
96
|
-
const std::string id0 = r._installEntryForTests(nullptr);
|
|
97
|
-
const std::string id1 = r._installEntryForTests(nullptr);
|
|
98
|
-
const std::string id2 = r._installEntryForTests(nullptr);
|
|
99
|
-
EXPECT_EQ(r.count(), 3u);
|
|
100
|
-
|
|
101
|
-
r.uninstall(id1); // remove the middle entry
|
|
102
|
-
EXPECT_EQ(r.count(), 2u);
|
|
103
|
-
|
|
104
|
-
// Snapshot should contain only id0 and id2, in some order — the
|
|
105
|
-
// contract doesn't promise insertion order survives uninstall
|
|
106
|
-
// (the erase-remove pattern is stable in practice but we don't
|
|
107
|
-
// pin that publicly).
|
|
108
|
-
const auto snap = r.snapshot();
|
|
109
|
-
std::vector<std::string> remainingIds;
|
|
110
|
-
remainingIds.reserve(snap.size());
|
|
111
|
-
for (const auto& entry : snap) {
|
|
112
|
-
remainingIds.push_back(entry.id);
|
|
113
|
-
}
|
|
114
|
-
std::sort(remainingIds.begin(), remainingIds.end());
|
|
115
|
-
EXPECT_EQ(remainingIds, (std::vector<std::string>{id0, id2}));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
TEST_F(StitcherWorkletRegistryTest, UninstallOfUnknownIdIsNoop) {
|
|
119
|
-
// Matches the JS-side `StitcherWorkletRegistry.uninstall` semantics
|
|
120
|
-
// (idempotent, no throw on unknown). Critical because the JS
|
|
121
|
-
// useEffect cleanup can fire after an unmount/remount race where the
|
|
122
|
-
// ID has already been removed.
|
|
123
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
124
|
-
r._installEntryForTests(nullptr);
|
|
125
|
-
EXPECT_EQ(r.count(), 1u);
|
|
126
|
-
EXPECT_NO_THROW(r.uninstall("host-does-not-exist"));
|
|
127
|
-
EXPECT_NO_THROW(r.uninstall(""));
|
|
128
|
-
EXPECT_EQ(r.count(), 1u); // existing entry untouched
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
TEST_F(StitcherWorkletRegistryTest, SnapshotIsIndependentOfFutureMutations) {
|
|
132
|
-
// Per header docstring: "mutations against the registry after
|
|
133
|
-
// `snapshot` returns do not affect the snapshot." This matters for
|
|
134
|
-
// the AR-session dispatch path, which snapshots and then iterates
|
|
135
|
-
// without holding the registry lock — concurrent uninstall on the
|
|
136
|
-
// JS thread must NOT invalidate the snapshot.
|
|
137
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
138
|
-
const std::string id0 = r._installEntryForTests(nullptr);
|
|
139
|
-
const std::string id1 = r._installEntryForTests(nullptr);
|
|
140
|
-
|
|
141
|
-
const auto snap = r.snapshot();
|
|
142
|
-
ASSERT_EQ(snap.size(), 2u);
|
|
143
|
-
|
|
144
|
-
r.uninstall(id0);
|
|
145
|
-
r.uninstall(id1);
|
|
146
|
-
EXPECT_EQ(r.count(), 0u);
|
|
147
|
-
|
|
148
|
-
// Snapshot still has both entries.
|
|
149
|
-
EXPECT_EQ(snap.size(), 2u);
|
|
150
|
-
EXPECT_EQ(snap[0].id, id0);
|
|
151
|
-
EXPECT_EQ(snap[1].id, id1);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
TEST_F(StitcherWorkletRegistryTest, ConcurrentInstallsYieldUniqueIds) {
|
|
155
|
-
// Many threads racing `_installEntryForTests` simultaneously must
|
|
156
|
-
// not see duplicate IDs (would indicate the mutex around _nextId is
|
|
157
|
-
// missing or broken). This is the per-instance equivalent of
|
|
158
|
-
// TransferredNV21Test's "only one of N concurrent callers wins"
|
|
159
|
-
// pattern, adapted for "all N callers succeed but produce distinct
|
|
160
|
-
// IDs".
|
|
161
|
-
auto& r = StitcherWorkletRegistry::shared();
|
|
162
|
-
constexpr int kThreads = 16;
|
|
163
|
-
constexpr int kPerThread = 32; // 512 total installs
|
|
164
|
-
|
|
165
|
-
std::vector<std::thread> workers;
|
|
166
|
-
workers.reserve(kThreads);
|
|
167
|
-
std::vector<std::vector<std::string>> idsPerThread(kThreads);
|
|
168
|
-
|
|
169
|
-
std::atomic<bool> go{false};
|
|
170
|
-
for (int t = 0; t < kThreads; ++t) {
|
|
171
|
-
workers.emplace_back([&, t]() {
|
|
172
|
-
while (!go.load(std::memory_order_acquire)) {
|
|
173
|
-
std::this_thread::yield();
|
|
174
|
-
}
|
|
175
|
-
for (int i = 0; i < kPerThread; ++i) {
|
|
176
|
-
idsPerThread[t].push_back(r._installEntryForTests(nullptr));
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
go.store(true, std::memory_order_release);
|
|
181
|
-
for (auto& w : workers) w.join();
|
|
182
|
-
|
|
183
|
-
// Aggregate every ID issued. Total count = kThreads * kPerThread;
|
|
184
|
-
// uniqueness = the set size matches.
|
|
185
|
-
std::set<std::string> allIds;
|
|
186
|
-
for (const auto& v : idsPerThread) {
|
|
187
|
-
for (const auto& id : v) {
|
|
188
|
-
allIds.insert(id);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
EXPECT_EQ(allIds.size(),
|
|
192
|
-
static_cast<std::size_t>(kThreads * kPerThread));
|
|
193
|
-
EXPECT_EQ(r.count(),
|
|
194
|
-
static_cast<std::size_t>(kThreads * kPerThread));
|
|
195
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IncrementalStitcherView — live preview component for the panorama
|
|
3
|
-
* engine. Renders the latest snapshot JPEG written by the native
|
|
4
|
-
* side, with confidence + hint overlays.
|
|
5
|
-
*
|
|
6
|
-
* Why <Image> + cache-bust query string instead of a custom native
|
|
7
|
-
* view: per the design doc's open question, the JPEG-write approach
|
|
8
|
-
* is V1; if perf measurements show we're hitting RN's image cache
|
|
9
|
-
* too hard, swap in an `Animated.Image` or a native UIView with
|
|
10
|
-
* an in-memory bitmap. Until then, the simple path keeps the
|
|
11
|
-
* cross-platform surface tiny.
|
|
12
|
-
*/
|
|
13
|
-
import React from 'react';
|
|
14
|
-
import { type ViewStyle } from 'react-native';
|
|
15
|
-
import type { IncrementalState } from './incremental';
|
|
16
|
-
import type { IncrementalHint } from './useIncrementalStitcher';
|
|
17
|
-
export interface IncrementalStitcherViewProps {
|
|
18
|
-
/** Latest engine state — typically `useIncrementalStitcher().state`. */
|
|
19
|
-
state: IncrementalState | null;
|
|
20
|
-
/**
|
|
21
|
-
* Active hint to surface as a banner overlay. Pass
|
|
22
|
-
* `useIncrementalStitcher().hint` directly; the view picks the
|
|
23
|
-
* right wording.
|
|
24
|
-
*/
|
|
25
|
-
hint: IncrementalHint;
|
|
26
|
-
/**
|
|
27
|
-
* Confidence ring colour driver — typically
|
|
28
|
-
* `useIncrementalStitcher().confidenceLevel`.
|
|
29
|
-
*/
|
|
30
|
-
confidenceLevel?: 'high' | 'medium' | null;
|
|
31
|
-
/** Outer container style (size, position). Required: the view
|
|
32
|
-
* has no intrinsic size since the panorama dimensions vary. */
|
|
33
|
-
style?: ViewStyle;
|
|
34
|
-
/**
|
|
35
|
-
* Optional override for the spinner shown before the first frame
|
|
36
|
-
* is accepted. Default is a subtle "Pan to begin" caption.
|
|
37
|
-
*/
|
|
38
|
-
emptyText?: string;
|
|
39
|
-
}
|
|
40
|
-
export declare function IncrementalStitcherView({ state, hint, confidenceLevel, style, emptyText, }: IncrementalStitcherViewProps): React.JSX.Element;
|
|
41
|
-
//# sourceMappingURL=IncrementalStitcherView.d.ts.map
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
/**
|
|
4
|
-
* IncrementalStitcherView — live preview component for the panorama
|
|
5
|
-
* engine. Renders the latest snapshot JPEG written by the native
|
|
6
|
-
* side, with confidence + hint overlays.
|
|
7
|
-
*
|
|
8
|
-
* Why <Image> + cache-bust query string instead of a custom native
|
|
9
|
-
* view: per the design doc's open question, the JPEG-write approach
|
|
10
|
-
* is V1; if perf measurements show we're hitting RN's image cache
|
|
11
|
-
* too hard, swap in an `Animated.Image` or a native UIView with
|
|
12
|
-
* an in-memory bitmap. Until then, the simple path keeps the
|
|
13
|
-
* cross-platform surface tiny.
|
|
14
|
-
*/
|
|
15
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
-
}
|
|
21
|
-
Object.defineProperty(o, k2, desc);
|
|
22
|
-
}) : (function(o, m, k, k2) {
|
|
23
|
-
if (k2 === undefined) k2 = k;
|
|
24
|
-
o[k2] = m[k];
|
|
25
|
-
}));
|
|
26
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
-
}) : function(o, v) {
|
|
29
|
-
o["default"] = v;
|
|
30
|
-
});
|
|
31
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
-
var ownKeys = function(o) {
|
|
33
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
-
var ar = [];
|
|
35
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
-
return ar;
|
|
37
|
-
};
|
|
38
|
-
return ownKeys(o);
|
|
39
|
-
};
|
|
40
|
-
return function (mod) {
|
|
41
|
-
if (mod && mod.__esModule) return mod;
|
|
42
|
-
var result = {};
|
|
43
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
-
__setModuleDefault(result, mod);
|
|
45
|
-
return result;
|
|
46
|
-
};
|
|
47
|
-
})();
|
|
48
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
-
exports.IncrementalStitcherView = IncrementalStitcherView;
|
|
50
|
-
const react_1 = __importStar(require("react"));
|
|
51
|
-
const react_native_1 = require("react-native");
|
|
52
|
-
function hintMessage(hint) {
|
|
53
|
-
switch (hint) {
|
|
54
|
-
case 'slow-down': return 'Slow down — alignment lost';
|
|
55
|
-
case 'scene-uniform': return 'Pan to a textured area';
|
|
56
|
-
case 'alignment-lost': return 'Slow down — re-acquiring alignment';
|
|
57
|
-
case 'tracking-poor': return 'Hold steady — AR re-acquiring';
|
|
58
|
-
default: return null;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function IncrementalStitcherView({ state, hint, confidenceLevel, style, emptyText = 'Pan to begin capturing', }) {
|
|
62
|
-
// Cache-bust the panorama URI. The native side rotates through
|
|
63
|
-
// 4 filenames so the path itself changes between snapshots, plus
|
|
64
|
-
// we tag with acceptedCount as belt-and-suspenders since RN's
|
|
65
|
-
// image cache on iOS sometimes ignores file:// query strings.
|
|
66
|
-
const imageUri = (0, react_1.useMemo)(() => {
|
|
67
|
-
if (!state?.panoramaPath)
|
|
68
|
-
return null;
|
|
69
|
-
return `file://${state.panoramaPath}?v=${state.acceptedCount}`;
|
|
70
|
-
}, [state?.panoramaPath, state?.acceptedCount]);
|
|
71
|
-
// Use the panorama's NATURAL aspect ratio so the strip widens as
|
|
72
|
-
// the user pans across. Falls back to 4:3 (a single frame's
|
|
73
|
-
// shape) before any snapshot has been written. Without this the
|
|
74
|
-
// PiP was forced into a 3:1 letterbox, cropping the actual
|
|
75
|
-
// panorama to a thin slice across the middle.
|
|
76
|
-
const naturalAspect = state?.width && state?.height && state.height > 0
|
|
77
|
-
? state.width / state.height
|
|
78
|
-
: 4 / 3;
|
|
79
|
-
const ringColor = confidenceLevel === 'high'
|
|
80
|
-
? '#1aaf5d'
|
|
81
|
-
: confidenceLevel === 'medium'
|
|
82
|
-
? '#e6b800'
|
|
83
|
-
: 'rgba(255,255,255,0.35)';
|
|
84
|
-
const message = hintMessage(hint);
|
|
85
|
-
return (react_1.default.createElement(react_native_1.View, { style: [styles.container, { aspectRatio: naturalAspect }, style] },
|
|
86
|
-
imageUri ? (
|
|
87
|
-
// `contain` so the FULL panorama is visible inside the
|
|
88
|
-
// strip, not cropped to a slice. Background fills the
|
|
89
|
-
// letterbox edges. Key={acceptedCount} forces RN to
|
|
90
|
-
// remount the Image component each accept — the surest
|
|
91
|
-
// way to defeat the native image cache on file:// URIs.
|
|
92
|
-
react_1.default.createElement(react_native_1.Image, { key: state?.acceptedCount ?? 0, source: { uri: imageUri }, style: react_native_1.StyleSheet.absoluteFill, resizeMode: "contain", fadeDuration: 0 })) : (react_1.default.createElement(react_native_1.View, { style: styles.empty },
|
|
93
|
-
react_1.default.createElement(react_native_1.ActivityIndicator, { color: "#fff" }),
|
|
94
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.emptyText }, emptyText))),
|
|
95
|
-
react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: [styles.ring, { borderColor: ringColor }] }),
|
|
96
|
-
message ? (react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: styles.hintBanner },
|
|
97
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.hintText }, message))) : null,
|
|
98
|
-
state ? (react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: styles.counterPill },
|
|
99
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.counterText },
|
|
100
|
-
state.acceptedCount,
|
|
101
|
-
" frame",
|
|
102
|
-
state.acceptedCount === 1 ? '' : 's'))) : null));
|
|
103
|
-
}
|
|
104
|
-
const styles = react_native_1.StyleSheet.create({
|
|
105
|
-
container: {
|
|
106
|
-
backgroundColor: 'rgba(0,0,0,0.7)',
|
|
107
|
-
overflow: 'hidden',
|
|
108
|
-
borderRadius: 8,
|
|
109
|
-
},
|
|
110
|
-
empty: {
|
|
111
|
-
...react_native_1.StyleSheet.absoluteFillObject,
|
|
112
|
-
alignItems: 'center',
|
|
113
|
-
justifyContent: 'center',
|
|
114
|
-
gap: 6,
|
|
115
|
-
},
|
|
116
|
-
emptyText: {
|
|
117
|
-
color: '#fff',
|
|
118
|
-
fontSize: 12,
|
|
119
|
-
opacity: 0.85,
|
|
120
|
-
},
|
|
121
|
-
ring: {
|
|
122
|
-
...react_native_1.StyleSheet.absoluteFillObject,
|
|
123
|
-
borderRadius: 8,
|
|
124
|
-
borderWidth: 2,
|
|
125
|
-
},
|
|
126
|
-
hintBanner: {
|
|
127
|
-
position: 'absolute',
|
|
128
|
-
left: 8,
|
|
129
|
-
right: 8,
|
|
130
|
-
bottom: 8,
|
|
131
|
-
paddingVertical: 4,
|
|
132
|
-
paddingHorizontal: 8,
|
|
133
|
-
backgroundColor: 'rgba(220, 53, 69, 0.92)',
|
|
134
|
-
borderRadius: 6,
|
|
135
|
-
},
|
|
136
|
-
hintText: {
|
|
137
|
-
color: '#fff',
|
|
138
|
-
fontSize: 11,
|
|
139
|
-
textAlign: 'center',
|
|
140
|
-
fontWeight: '500',
|
|
141
|
-
},
|
|
142
|
-
counterPill: {
|
|
143
|
-
position: 'absolute',
|
|
144
|
-
top: 6,
|
|
145
|
-
right: 6,
|
|
146
|
-
paddingVertical: 2,
|
|
147
|
-
paddingHorizontal: 8,
|
|
148
|
-
backgroundColor: 'rgba(0, 0, 0, 0.55)',
|
|
149
|
-
borderRadius: 10,
|
|
150
|
-
},
|
|
151
|
-
counterText: {
|
|
152
|
-
color: '#fff',
|
|
153
|
-
fontSize: 10,
|
|
154
|
-
fontWeight: '500',
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
//# sourceMappingURL=IncrementalStitcherView.js.map
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import type { StitcherFrameProcessor } from './StitcherFrame';
|
|
2
|
-
/**
|
|
3
|
-
* v0.8.0 Phase 4a — process-scope registry of host-supplied worklets
|
|
4
|
-
* that the v0.8.0 `useFrameProcessor` hook registers into.
|
|
5
|
-
*
|
|
6
|
-
* ## What this is (Phase 4a)
|
|
7
|
-
*
|
|
8
|
-
* A plain JS singleton holding an ordered list of registered
|
|
9
|
-
* worklets. Hosts mount the `useFrameProcessor` hook (in this
|
|
10
|
-
* directory); the hook registers its worklet into this singleton
|
|
11
|
-
* on mount and unregisters on unmount. Each entry carries:
|
|
12
|
-
*
|
|
13
|
-
* - `id`: stable identifier issued by `register`; passed to
|
|
14
|
-
* `unregister`.
|
|
15
|
-
* - `worklet`: the host's `StitcherFrameProcessor` function.
|
|
16
|
-
* MUST be `'worklet'`-prefixed at the call site (TS can't
|
|
17
|
-
* enforce that — convention).
|
|
18
|
-
* - `isFirstParty`: `false` for host-supplied worklets;
|
|
19
|
-
* reserved for the lib's own first-party stitching path which
|
|
20
|
-
* today is wired natively (not through this registry).
|
|
21
|
-
*
|
|
22
|
-
* Order is stable: first-party entries (none in Phase 4a) come
|
|
23
|
-
* first, then host entries by registration order. Re-registration
|
|
24
|
-
* of the same worklet by identity yields a new entry — hosts that
|
|
25
|
-
* re-render and call `register` again ARE responsible for calling
|
|
26
|
-
* `unregister` first. The `useFrameProcessor` hook handles this
|
|
27
|
-
* via its `deps` dependency array.
|
|
28
|
-
*
|
|
29
|
-
* ## What this is NOT (Phase 4b)
|
|
30
|
-
*
|
|
31
|
-
* **The native AR worklet runtime does NOT yet read this registry.**
|
|
32
|
-
* Worklets registered here for AR-mode captures will not fire
|
|
33
|
-
* until Phase 4b lands the cross-runtime handoff (a
|
|
34
|
-
* worklets-core `SharedValue` mirror that `RNSARWorkletRuntime`
|
|
35
|
-
* reads on each `dispatchFrame:pose:` call; the runtime then
|
|
36
|
-
* constructs a `StitcherFrameHostObject` + invokes each
|
|
37
|
-
* registered worklet via `RNWorklet::WorkletInvoker::call`).
|
|
38
|
-
*
|
|
39
|
-
* In non-AR mode the host-supplied worklet IS invoked, but via
|
|
40
|
-
* vision-camera's Frame Processor runtime directly (the
|
|
41
|
-
* `useFrameProcessor` hook returns vc's processor object which
|
|
42
|
-
* `<Camera>` passes to vision-camera). So Phase 4a's public API
|
|
43
|
-
* is fully functional for non-AR; AR is API-stable but
|
|
44
|
-
* runtime-deferred.
|
|
45
|
-
*
|
|
46
|
-
* ## Singleton lifetime
|
|
47
|
-
*
|
|
48
|
-
* The registry is a module-level instance. It lives for the
|
|
49
|
-
* lifetime of the JS runtime (= until app reload). Entries
|
|
50
|
-
* accumulate only via `register` and shed only via `unregister`
|
|
51
|
-
* — no GC / weak-ref logic. Hosts that mount `useFrameProcessor`
|
|
52
|
-
* inside React components MUST rely on the hook's effect cleanup
|
|
53
|
-
* to unregister on unmount, or they'll leak entries until
|
|
54
|
-
* reload. The hook handles this correctly today.
|
|
55
|
-
*
|
|
56
|
-
* ## Why a singleton (vs context provider)
|
|
57
|
-
*
|
|
58
|
-
* The native AR worklet runtime is itself a process-scope
|
|
59
|
-
* singleton (`RNSARWorkletRuntime`, `StitcherWorkletRuntime`).
|
|
60
|
-
* The Phase 4b handoff between TS and native is necessarily
|
|
61
|
-
* process-scope. Wrapping the registry in a React context
|
|
62
|
-
* would force every consumer to be in the same provider tree
|
|
63
|
-
* which is friction for layer-2 hosts that compose
|
|
64
|
-
* `<ARCameraView>` / `useIncrementalStitcher` themselves. The
|
|
65
|
-
* singleton is the right shape; the React-level ergonomics are
|
|
66
|
-
* provided by the `useFrameProcessor` hook.
|
|
67
|
-
*/
|
|
68
|
-
export interface StitcherWorkletEntry {
|
|
69
|
-
readonly id: string;
|
|
70
|
-
readonly worklet: StitcherFrameProcessor;
|
|
71
|
-
readonly isFirstParty: boolean;
|
|
72
|
-
}
|
|
73
|
-
declare class Registry {
|
|
74
|
-
private entries;
|
|
75
|
-
private nextHostCounter;
|
|
76
|
-
/**
|
|
77
|
-
* Register a worklet. Returns a stable ID for `unregister`.
|
|
78
|
-
*
|
|
79
|
-
* Entries are appended in registration order; first-party
|
|
80
|
-
* entries (if any are added in future) sort to the front.
|
|
81
|
-
*/
|
|
82
|
-
register(opts: {
|
|
83
|
-
worklet: StitcherFrameProcessor;
|
|
84
|
-
isFirstParty?: boolean;
|
|
85
|
-
}): string;
|
|
86
|
-
/**
|
|
87
|
-
* Remove a previously-registered worklet by ID. No-op if the ID
|
|
88
|
-
* isn't found. Hosts call this in their effect's cleanup.
|
|
89
|
-
*/
|
|
90
|
-
unregister(id: string): void;
|
|
91
|
-
/**
|
|
92
|
-
* Snapshot the current entries. Returned array is a copy —
|
|
93
|
-
* mutations don't affect the registry. Phase 4b's native
|
|
94
|
-
* handoff will read a `SharedValue` mirror of this list so the
|
|
95
|
-
* AR runtime doesn't need a JS-thread hop on the hot per-frame
|
|
96
|
-
* path; for Phase 4a this method is the JS-side accessor.
|
|
97
|
-
*/
|
|
98
|
-
getEntries(): readonly StitcherWorkletEntry[];
|
|
99
|
-
/**
|
|
100
|
-
* Total number of registered worklets (first-party + host).
|
|
101
|
-
* Useful for diagnostics + tests.
|
|
102
|
-
*/
|
|
103
|
-
get count(): number;
|
|
104
|
-
/**
|
|
105
|
-
* Test-only — clear all entries. NOT exported from
|
|
106
|
-
* `src/index.ts`. Used in unit tests to reset state between
|
|
107
|
-
* cases.
|
|
108
|
-
*/
|
|
109
|
-
_resetForTests(): void;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Process-scope singleton. Imported by `useFrameProcessor` (in
|
|
113
|
-
* this directory) + by the Phase 4b native-handoff code (TBD).
|
|
114
|
-
*/
|
|
115
|
-
export declare const StitcherWorkletRegistry: Registry;
|
|
116
|
-
export {};
|
|
117
|
-
//# sourceMappingURL=StitcherWorkletRegistry.d.ts.map
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.StitcherWorkletRegistry = void 0;
|
|
5
|
-
class Registry {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.entries = [];
|
|
8
|
-
this.nextHostCounter = 0;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Register a worklet. Returns a stable ID for `unregister`.
|
|
12
|
-
*
|
|
13
|
-
* Entries are appended in registration order; first-party
|
|
14
|
-
* entries (if any are added in future) sort to the front.
|
|
15
|
-
*/
|
|
16
|
-
register(opts) {
|
|
17
|
-
const isFirstParty = opts.isFirstParty ?? false;
|
|
18
|
-
const id = isFirstParty
|
|
19
|
-
? `fp-${this.nextHostCounter++}`
|
|
20
|
-
: `host-${this.nextHostCounter++}`;
|
|
21
|
-
const entry = {
|
|
22
|
-
id,
|
|
23
|
-
worklet: opts.worklet,
|
|
24
|
-
isFirstParty,
|
|
25
|
-
};
|
|
26
|
-
this.entries.push(entry);
|
|
27
|
-
// Re-sort so first-party always runs before host entries.
|
|
28
|
-
// Stable sort: registration order is preserved within each
|
|
29
|
-
// partition. Single-pass O(n log n) is fine — registration
|
|
30
|
-
// is rare (per-`<Camera>`-mount, not per-frame).
|
|
31
|
-
this.entries.sort((a, b) => {
|
|
32
|
-
if (a.isFirstParty !== b.isFirstParty) {
|
|
33
|
-
return a.isFirstParty ? -1 : 1;
|
|
34
|
-
}
|
|
35
|
-
return 0;
|
|
36
|
-
});
|
|
37
|
-
return id;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Remove a previously-registered worklet by ID. No-op if the ID
|
|
41
|
-
* isn't found. Hosts call this in their effect's cleanup.
|
|
42
|
-
*/
|
|
43
|
-
unregister(id) {
|
|
44
|
-
this.entries = this.entries.filter((e) => e.id !== id);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Snapshot the current entries. Returned array is a copy —
|
|
48
|
-
* mutations don't affect the registry. Phase 4b's native
|
|
49
|
-
* handoff will read a `SharedValue` mirror of this list so the
|
|
50
|
-
* AR runtime doesn't need a JS-thread hop on the hot per-frame
|
|
51
|
-
* path; for Phase 4a this method is the JS-side accessor.
|
|
52
|
-
*/
|
|
53
|
-
getEntries() {
|
|
54
|
-
return [...this.entries];
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Total number of registered worklets (first-party + host).
|
|
58
|
-
* Useful for diagnostics + tests.
|
|
59
|
-
*/
|
|
60
|
-
get count() {
|
|
61
|
-
return this.entries.length;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Test-only — clear all entries. NOT exported from
|
|
65
|
-
* `src/index.ts`. Used in unit tests to reset state between
|
|
66
|
-
* cases.
|
|
67
|
-
*/
|
|
68
|
-
_resetForTests() {
|
|
69
|
-
this.entries = [];
|
|
70
|
-
this.nextHostCounter = 0;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Process-scope singleton. Imported by `useFrameProcessor` (in
|
|
75
|
-
* this directory) + by the Phase 4b native-handoff code (TBD).
|
|
76
|
-
*/
|
|
77
|
-
exports.StitcherWorkletRegistry = new Registry();
|
|
78
|
-
//# sourceMappingURL=StitcherWorkletRegistry.js.map
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare function ensureStitcherProxyInstalled(): boolean;
|
|
2
|
-
/**
|
|
3
|
-
* Test-only — reset module-internal state. Used by jest to allow
|
|
4
|
-
* multiple test cases to re-trigger the install path independently.
|
|
5
|
-
* NOT exported from `src/index.ts`.
|
|
6
|
-
*/
|
|
7
|
-
export declare function _resetStitcherProxyInstallStateForTests(): void;
|
|
8
|
-
//# sourceMappingURL=ensureStitcherProxyInstalled.d.ts.map
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.ensureStitcherProxyInstalled = ensureStitcherProxyInstalled;
|
|
5
|
-
exports._resetStitcherProxyInstallStateForTests = _resetStitcherProxyInstallStateForTests;
|
|
6
|
-
const react_native_1 = require("react-native");
|
|
7
|
-
/**
|
|
8
|
-
* `__DEV__` is RN's global dev-flag. Guard the read with `typeof`
|
|
9
|
-
* so the helper works in any environment that imports it without
|
|
10
|
-
* defining __DEV__ (jest, SSR, custom tooling). Same pattern RN's
|
|
11
|
-
* own debug code uses.
|
|
12
|
-
*/
|
|
13
|
-
function isDev() {
|
|
14
|
-
return typeof __DEV__ !== 'undefined' && __DEV__;
|
|
15
|
-
}
|
|
16
|
-
let installed = false;
|
|
17
|
-
function ensureStitcherProxyInstalled() {
|
|
18
|
-
if (installed)
|
|
19
|
-
return true;
|
|
20
|
-
// Already installed by an earlier hook mount. Cheap fast-path.
|
|
21
|
-
if (typeof globalThis.__stitcherProxy !== 'undefined') {
|
|
22
|
-
installed = true;
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
const mod = react_native_1.NativeModules
|
|
26
|
-
.StitcherJsiInstaller;
|
|
27
|
-
if (mod == null || typeof mod.install !== 'function') {
|
|
28
|
-
// Module not present — Android until Phase 4b.ii lands, or
|
|
29
|
-
// an old iOS build. Surface this once at debug-info level so
|
|
30
|
-
// the host can see "your worklets are JS-registered only" in
|
|
31
|
-
// logcat / Console.app without a noisy per-frame warning.
|
|
32
|
-
if (isDev() && !warnedAboutMissingModule) {
|
|
33
|
-
warnedAboutMissingModule = true;
|
|
34
|
-
console.info('[react-native-image-stitcher] StitcherJsiInstaller native ' +
|
|
35
|
-
'module not found; host worklets registered in JS-side ' +
|
|
36
|
-
'registry only. AR-mode dispatch requires the native install ' +
|
|
37
|
-
'(iOS Phase 4b.i — included in v0.8.0; Android Phase 4b.ii ' +
|
|
38
|
-
'— follow-up release).');
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
const ok = mod.install();
|
|
44
|
-
if (!ok) {
|
|
45
|
-
// Native module ran but couldn't install (JSI runtime
|
|
46
|
-
// unreachable). Same fallback as the missing-module case.
|
|
47
|
-
if (isDev() && !warnedAboutFailedInstall) {
|
|
48
|
-
warnedAboutFailedInstall = true;
|
|
49
|
-
console.info('[react-native-image-stitcher] StitcherJsiInstaller.install() ' +
|
|
50
|
-
'returned false (JSI runtime unreachable — remote debug ' +
|
|
51
|
-
'mode?). Falling back to JS-side host worklet registry.');
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
installed = true;
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
if (isDev() && !warnedAboutFailedInstall) {
|
|
60
|
-
warnedAboutFailedInstall = true;
|
|
61
|
-
console.info('[react-native-image-stitcher] StitcherJsiInstaller.install() ' +
|
|
62
|
-
'threw: ' +
|
|
63
|
-
String(err) +
|
|
64
|
-
'. Falling back to JS-side host worklet registry.');
|
|
65
|
-
}
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
let warnedAboutMissingModule = false;
|
|
70
|
-
let warnedAboutFailedInstall = false;
|
|
71
|
-
/**
|
|
72
|
-
* Test-only — reset module-internal state. Used by jest to allow
|
|
73
|
-
* multiple test cases to re-trigger the install path independently.
|
|
74
|
-
* NOT exported from `src/index.ts`.
|
|
75
|
-
*/
|
|
76
|
-
function _resetStitcherProxyInstallStateForTests() {
|
|
77
|
-
installed = false;
|
|
78
|
-
warnedAboutMissingModule = false;
|
|
79
|
-
warnedAboutFailedInstall = false;
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=ensureStitcherProxyInstalled.js.map
|