yaver-feedback-react-native 0.7.12 → 0.7.14
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/app.plugin.js +75 -79
- package/package.json +1 -1
package/app.plugin.js
CHANGED
|
@@ -113,65 +113,42 @@ function withYaverHotReloadNativeModule(config) {
|
|
|
113
113
|
// them into the app target. Without this, the files exist on disk
|
|
114
114
|
// but are invisible to the build system.
|
|
115
115
|
config = withXcodeProject(config, (config) => {
|
|
116
|
-
const
|
|
116
|
+
const proj = config.modResults;
|
|
117
117
|
const appName = config.modRequest.projectName;
|
|
118
118
|
if (!appName) return config;
|
|
119
119
|
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
break;
|
|
120
|
+
// Look up the group key for the app's source folder (same group
|
|
121
|
+
// that holds AppDelegate.swift). Expo's naming is consistent —
|
|
122
|
+
// projectName === group name in the tree.
|
|
123
|
+
const groupKey =
|
|
124
|
+
proj.findPBXGroupKey({ name: appName }) ||
|
|
125
|
+
proj.findPBXGroupKey({ path: appName });
|
|
126
|
+
if (!groupKey) return config;
|
|
127
|
+
|
|
128
|
+
// Target UUID — getFirstTarget is the app target in a standard
|
|
129
|
+
// Expo project. For multi-target projects, users can opt out via
|
|
130
|
+
// enableHotReload: false.
|
|
131
|
+
const target = proj.getFirstTarget();
|
|
132
|
+
if (!target || !target.uuid) return config;
|
|
133
|
+
|
|
134
|
+
const filesToAdd = ["YaverHotReload.swift", "YaverHotReload.m"];
|
|
135
|
+
for (const fileName of filesToAdd) {
|
|
136
|
+
const relPath = `${appName}/${fileName}`;
|
|
137
|
+
// addSourceFile registers PBXFileReference + PBXBuildFile, adds
|
|
138
|
+
// the file to the group, and wires it into the target's
|
|
139
|
+
// Sources build phase — which is exactly what we need. It's
|
|
140
|
+
// idempotent in practice because the sdk-level copyFileSync
|
|
141
|
+
// step always writes the file, and addSourceFile is a no-op if
|
|
142
|
+
// the reference already exists.
|
|
143
|
+
if (!proj.hasFile || !proj.hasFile(relPath)) {
|
|
144
|
+
try {
|
|
145
|
+
proj.addSourceFile(relPath, { target: target.uuid }, groupKey);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
// If a duplicate slips through, xcode-lib throws; safe to
|
|
148
|
+
// ignore since the file already being registered is the
|
|
149
|
+
// desired state.
|
|
151
150
|
}
|
|
152
151
|
}
|
|
153
|
-
if (sourcesBuildPhase) break;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const swiftName = "YaverHotReload.swift";
|
|
157
|
-
const objcName = "YaverHotReload.m";
|
|
158
|
-
|
|
159
|
-
// addSourceFile registers the file as a PBXFileReference, adds a
|
|
160
|
-
// PBXBuildFile entry, drops it into the pbx group, and adds it to
|
|
161
|
-
// the sources build phase — exactly what we need.
|
|
162
|
-
if (!pbxHasFile(pbx, swiftName)) {
|
|
163
|
-
pbx.addSourceFile(
|
|
164
|
-
`${appName}/${swiftName}`,
|
|
165
|
-
{ target: findTargetUuidByName(pbx, appName) },
|
|
166
|
-
groupUuid,
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
if (!pbxHasFile(pbx, objcName)) {
|
|
170
|
-
pbx.addSourceFile(
|
|
171
|
-
`${appName}/${objcName}`,
|
|
172
|
-
{ target: findTargetUuidByName(pbx, appName) },
|
|
173
|
-
groupUuid,
|
|
174
|
-
);
|
|
175
152
|
}
|
|
176
153
|
|
|
177
154
|
return config;
|
|
@@ -180,28 +157,6 @@ function withYaverHotReloadNativeModule(config) {
|
|
|
180
157
|
return config;
|
|
181
158
|
}
|
|
182
159
|
|
|
183
|
-
function pbxHasFile(pbx, basename) {
|
|
184
|
-
const refs = pbx.pbxFileReferenceSection();
|
|
185
|
-
for (const uuid of Object.keys(refs)) {
|
|
186
|
-
if (uuid.endsWith("_comment")) continue;
|
|
187
|
-
const ref = refs[uuid];
|
|
188
|
-
if (!ref || typeof ref !== "object") continue;
|
|
189
|
-
const pathValue = (ref.path || "").replace(/"/g, "");
|
|
190
|
-
if (pathValue.endsWith(basename)) return true;
|
|
191
|
-
}
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function findTargetUuidByName(pbx, appName) {
|
|
196
|
-
const section = pbx.pbxNativeTargetSection();
|
|
197
|
-
for (const uuid of Object.keys(section)) {
|
|
198
|
-
if (uuid.endsWith("_comment")) continue;
|
|
199
|
-
const target = section[uuid];
|
|
200
|
-
if (target && target.name === appName) return uuid;
|
|
201
|
-
}
|
|
202
|
-
return undefined;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
160
|
/**
|
|
206
161
|
* Patch AppDelegate to:
|
|
207
162
|
* 1. Return hot-reloaded bundle URL on startup (so reloaded bundle persists)
|
|
@@ -233,9 +188,22 @@ function withYaverAppDelegateHook(config) {
|
|
|
233
188
|
);
|
|
234
189
|
}
|
|
235
190
|
|
|
236
|
-
// 2. Add reload notification handler and bridge recreation logic
|
|
237
|
-
//
|
|
238
|
-
|
|
191
|
+
// 2. Add reload notification handler and bridge recreation logic.
|
|
192
|
+
//
|
|
193
|
+
// Must be inserted into the AppDelegate class — NOT ReactNativeDelegate
|
|
194
|
+
// (a separate class below it in the same file). The handler accesses
|
|
195
|
+
// `self.window`, `self.reactNativeDelegate`, `self.reactNativeFactory`,
|
|
196
|
+
// and `self.bindReactNativeFactory(...)` — all of which only exist
|
|
197
|
+
// on AppDelegate. An earlier version of this plugin used
|
|
198
|
+
// lastIndexOf("}"), which in modern Expo templates lands inside
|
|
199
|
+
// ReactNativeDelegate, producing build errors like
|
|
200
|
+
// "cannot find 'setupYaverHotReload' in scope"
|
|
201
|
+
// "value of type 'ReactNativeDelegate' has no member 'window'"
|
|
202
|
+
//
|
|
203
|
+
// The anchor we want is the closing brace of the AppDelegate class
|
|
204
|
+
// declaration itself. Find its opening, then walk braces to its
|
|
205
|
+
// matching close.
|
|
206
|
+
const classCloseIndex = findAppDelegateClassClose(patched);
|
|
239
207
|
if (classCloseIndex > 0) {
|
|
240
208
|
const reloadHandler = `
|
|
241
209
|
// MARK: - Yaver Feedback SDK Hot Reload
|
|
@@ -343,6 +311,34 @@ function withYaverAppDelegateHook(config) {
|
|
|
343
311
|
});
|
|
344
312
|
}
|
|
345
313
|
|
|
314
|
+
// Locate the closing brace of `class AppDelegate: ...` in an Expo
|
|
315
|
+
// Swift AppDelegate file. Returns the index of the matching `}` for
|
|
316
|
+
// the AppDelegate class's opening `{`, or -1 if not found. We need
|
|
317
|
+
// this because Expo's modern template declares TWO classes in the
|
|
318
|
+
// same file (AppDelegate + ReactNativeDelegate), and the SDK's
|
|
319
|
+
// reload handler only makes sense on the AppDelegate one.
|
|
320
|
+
function findAppDelegateClassClose(contents) {
|
|
321
|
+
// Match both `public class AppDelegate` and `class AppDelegate`,
|
|
322
|
+
// with either inheritance colon or a plain body.
|
|
323
|
+
const headerMatch = contents.match(/class\s+AppDelegate\s*[:{][^{]*\{/);
|
|
324
|
+
if (!headerMatch) return -1;
|
|
325
|
+
const bodyStart = headerMatch.index + headerMatch[0].length - 1; // index of the opening `{`
|
|
326
|
+
// Walk braces to find the matching close. Minimal — we don't try
|
|
327
|
+
// to parse strings/comments because the file is machine-generated
|
|
328
|
+
// by Expo, so braces inside strings are not a realistic concern
|
|
329
|
+
// at this layer.
|
|
330
|
+
let depth = 0;
|
|
331
|
+
for (let i = bodyStart; i < contents.length; i++) {
|
|
332
|
+
const ch = contents[i];
|
|
333
|
+
if (ch === "{") depth++;
|
|
334
|
+
else if (ch === "}") {
|
|
335
|
+
depth--;
|
|
336
|
+
if (depth === 0) return i;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return -1;
|
|
340
|
+
}
|
|
341
|
+
|
|
346
342
|
/**
|
|
347
343
|
* Copy Android native module source files and register the package.
|
|
348
344
|
* Also patches MainApplication to use hot-reloaded bundle on startup.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.14",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver — bug reports, screen recording, voice annotations, and local-first developer workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|