vxrn 2.0.0-beta.137.1 → 2.0.0-beta.138.1
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/dist/exports/prebuildWithoutExpo.mjs +76 -33
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +147 -79
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/dist/utils/nativeSourceContract.mjs +22 -10
- package/dist/utils/nativeSourceContract.mjs.map +1 -1
- package/dist/utils/nativeSourceContract.native.js +22 -10
- package/dist/utils/nativeSourceContract.native.js.map +1 -1
- package/expo-plugin.cjs +3 -1
- package/package.json +10 -10
- package/src/exports/expoPlugin.test.mjs +1 -0
- package/src/exports/prebuildWithoutExpo.test.ts +24 -2
- package/src/exports/prebuildWithoutExpo.ts +91 -51
- package/src/utils/nativeSourceContract.ts +23 -10
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
- package/types/utils/nativeSourceContract.d.ts.map +1 -1
|
@@ -75,21 +75,14 @@ import ReactAppDependencyProvider
|
|
|
75
75
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
76
76
|
var window: UIWindow?
|
|
77
77
|
|
|
78
|
-
var reactNativeDelegate: ReactNativeDelegate?
|
|
79
|
-
var reactNativeFactory: RCTReactNativeFactory?
|
|
80
|
-
|
|
81
78
|
func scene(
|
|
82
79
|
_ scene: UIScene,
|
|
83
80
|
willConnectTo session: UISceneSession,
|
|
84
81
|
options connectionOptions: UIScene.ConnectionOptions
|
|
85
82
|
) {
|
|
86
83
|
guard let windowScene = scene as? UIWindowScene else { return }
|
|
87
|
-
let
|
|
88
|
-
|
|
89
|
-
delegate.dependencyProvider = RCTAppDependencyProvider()
|
|
90
|
-
|
|
91
|
-
reactNativeDelegate = delegate
|
|
92
|
-
reactNativeFactory = factory
|
|
84
|
+
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
|
|
85
|
+
let factory = appDelegate.reactNativeFactory else { return }
|
|
93
86
|
|
|
94
87
|
let window = UIWindow(windowScene: windowScene)
|
|
95
88
|
self.window = window
|
|
@@ -165,7 +158,7 @@ function patchIosInfoPlistSceneManifest(rendered) {
|
|
|
165
158
|
</dict>
|
|
166
159
|
${anchor}`);
|
|
167
160
|
}
|
|
168
|
-
function patchIosAppDelegateSceneLifecycle(rendered, appName) {
|
|
161
|
+
function patchIosAppDelegateSceneLifecycle(rendered, appName, backgroundTasks) {
|
|
169
162
|
const anchor = `@main
|
|
170
163
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
171
164
|
var window: UIWindow?
|
|
@@ -200,11 +193,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
|
200
193
|
}
|
|
201
194
|
return rendered.replace(anchor, `@main
|
|
202
195
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
196
|
+
var reactNativeDelegate: ReactNativeDelegate?
|
|
197
|
+
var reactNativeFactory: RCTReactNativeFactory?
|
|
198
|
+
|
|
203
199
|
func application(
|
|
204
200
|
_ application: UIApplication,
|
|
205
201
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
206
202
|
) -> Bool {
|
|
207
|
-
|
|
203
|
+
let delegate = ReactNativeDelegate()
|
|
204
|
+
let factory = RCTReactNativeFactory(delegate: delegate)
|
|
205
|
+
delegate.dependencyProvider = RCTAppDependencyProvider()
|
|
206
|
+
reactNativeDelegate = delegate
|
|
207
|
+
reactNativeFactory = factory
|
|
208
|
+
${backgroundTasks ? ` OneBackgroundTasksRegisterHost(factory, launchOptions)
|
|
209
|
+
` : ""} return true
|
|
208
210
|
}
|
|
209
211
|
}`);
|
|
210
212
|
}
|
|
@@ -212,9 +214,9 @@ const ONE_BRIDGING_HEADER_NAME = "One-Bridging-Header.h";
|
|
|
212
214
|
function renderOneBridgingHeader(app) {
|
|
213
215
|
const imports = [nativeProjectPatches.ONE_LAUNCH_SCREEN.bridgingHeaderImport];
|
|
214
216
|
if (app.updates !== void 0) imports.push(updatesHost.bridgingHeaderImport);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// One module.
|
|
217
|
+
if (app.ios?.backgroundTasks !== void 0) imports.push("#import \"OneBackgroundTasksBridge.h\"");
|
|
218
|
+
return `// generated by one prebuild: exposes One's c entry points to AppDelegate
|
|
219
|
+
// without importing the One module.
|
|
218
220
|
${imports.join("\n")}
|
|
219
221
|
`;
|
|
220
222
|
}
|
|
@@ -1026,30 +1028,43 @@ class OneWidgetsBridge: RCTEventEmitter {
|
|
|
1026
1028
|
async function generateAppIcons(args) {
|
|
1027
1029
|
const { root, dest, platform, app } = args;
|
|
1028
1030
|
if (!app.icon) return;
|
|
1031
|
+
if (platform === "ios") {
|
|
1032
|
+
const assetsDir = path.join(dest, app.name, "Images.xcassets");
|
|
1033
|
+
const template = JSON.parse(FSExtra.readFileSync(path.join(assetsDir, "AppIcon.appiconset", "Contents.json"), "utf8"));
|
|
1034
|
+
const icons = [["AppIcon", app.icon], ...Object.entries(app.ios?.alternateIcons ?? {})];
|
|
1035
|
+
for (const [name, icon] of icons) {
|
|
1036
|
+
const source2 = path.resolve(root, icon.source);
|
|
1037
|
+
if (!FSExtra.existsSync(source2)) {
|
|
1038
|
+
throw new Error(`[vxrn] native.app icon source does not exist: ${source2}`);
|
|
1039
|
+
}
|
|
1040
|
+
const metadata2 = await sharp(source2).metadata();
|
|
1041
|
+
if (metadata2.width !== metadata2.height || metadata2.width === void 0 || metadata2.width < 1024) {
|
|
1042
|
+
throw new Error(`[vxrn] native.app icon source must be a square image at least 1024px wide: ${source2}`);
|
|
1043
|
+
}
|
|
1044
|
+
const iconDir = path.join(assetsDir, `${name}.appiconset`);
|
|
1045
|
+
FSExtra.mkdirSync(iconDir, { recursive: true });
|
|
1046
|
+
const contents = structuredClone(template);
|
|
1047
|
+
for (const image of contents.images) {
|
|
1048
|
+
const points = Number.parseFloat(image.size.split("x")[0]);
|
|
1049
|
+
const scale = Number.parseInt(image.scale, 10);
|
|
1050
|
+
const pixels = points * scale;
|
|
1051
|
+
const filename = image.idiom === "ios-marketing" ? "icon-1024.png" : `icon-${points}@${image.scale}.png`;
|
|
1052
|
+
image.filename = filename;
|
|
1053
|
+
await sharp(source2).rotate().resize(pixels, pixels, { fit: "cover" }).flatten({ background: icon.backgroundColor }).png().toFile(path.join(iconDir, filename));
|
|
1054
|
+
}
|
|
1055
|
+
FSExtra.writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify(contents, null, 2)}
|
|
1056
|
+
`);
|
|
1057
|
+
}
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1029
1060
|
const source = path.resolve(root, app.icon.source);
|
|
1030
1061
|
if (!FSExtra.existsSync(source)) {
|
|
1031
1062
|
throw new Error(`[vxrn] native.app.icon source does not exist: ${source}`);
|
|
1032
1063
|
}
|
|
1033
1064
|
const metadata = await sharp(source).metadata();
|
|
1034
|
-
if (metadata.width
|
|
1065
|
+
if (metadata.width !== metadata.height || metadata.width === void 0 || metadata.width < 1024) {
|
|
1035
1066
|
throw new Error("[vxrn] native.app.icon source must be a square image at least 1024px wide");
|
|
1036
1067
|
}
|
|
1037
|
-
if (platform === "ios") {
|
|
1038
|
-
const iconDir = path.join(dest, app.name, "Images.xcassets", "AppIcon.appiconset");
|
|
1039
|
-
const contentsPath = path.join(iconDir, "Contents.json");
|
|
1040
|
-
const contents = JSON.parse(FSExtra.readFileSync(contentsPath, "utf8"));
|
|
1041
|
-
for (const image of contents.images) {
|
|
1042
|
-
const points = Number.parseFloat(image.size.split("x")[0]);
|
|
1043
|
-
const scale = Number.parseInt(image.scale, 10);
|
|
1044
|
-
const pixels = points * scale;
|
|
1045
|
-
const filename = image.idiom === "ios-marketing" ? "icon-1024.png" : `icon-${points}@${image.scale}.png`;
|
|
1046
|
-
image.filename = filename;
|
|
1047
|
-
await sharp(source).rotate().resize(pixels, pixels, { fit: "cover" }).flatten({ background: app.icon.backgroundColor }).png().toFile(path.join(iconDir, filename));
|
|
1048
|
-
}
|
|
1049
|
-
FSExtra.writeFileSync(contentsPath, `${JSON.stringify(contents, null, 2)}
|
|
1050
|
-
`);
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
1068
|
for (const [density, multiplier] of Object.entries(ANDROID_DENSITIES)) {
|
|
1054
1069
|
const pixels = 48 * multiplier;
|
|
1055
1070
|
const iconDir = path.join(dest, "app", "src", "main", "res", `mipmap-${density}`);
|
|
@@ -1396,6 +1411,9 @@ ${schemes.map((scheme) => ` <string>${scheme}</string>`).join("\n")}
|
|
|
1396
1411
|
<key>LSSupportsOpeningDocumentsInPlace</key>
|
|
1397
1412
|
<true/>`);
|
|
1398
1413
|
}
|
|
1414
|
+
if (app.photoLibrary?.readWrite !== void 0) {
|
|
1415
|
+
stamps.push(" <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>\n <true/>");
|
|
1416
|
+
}
|
|
1399
1417
|
if (app.notifications !== void 0) {
|
|
1400
1418
|
stamps.push(` <key>${notificationsHost.enabledInfoPlistKey}</key>
|
|
1401
1419
|
<true/>`);
|
|
@@ -1407,7 +1425,23 @@ ${schemes.map((scheme) => ` <string>${scheme}</string>`).join("\n")}
|
|
|
1407
1425
|
if (app.ios?.widgets) {
|
|
1408
1426
|
stamps.push(" <key>NSSupportsLiveActivities</key>\n <true/>");
|
|
1409
1427
|
}
|
|
1410
|
-
const
|
|
1428
|
+
const refreshTasks = app.ios?.backgroundTasks?.refresh ?? [];
|
|
1429
|
+
const processingTasks = app.ios?.backgroundTasks?.processing ?? [];
|
|
1430
|
+
if (refreshTasks.length || processingTasks.length) {
|
|
1431
|
+
const plistArray = (key, identifiers) => ` <key>${key}</key>
|
|
1432
|
+
<array>
|
|
1433
|
+
${identifiers.map((identifier) => ` <string>${escapeXml(identifier)}</string>`).join("\n")}
|
|
1434
|
+
</array>`;
|
|
1435
|
+
stamps.push(plistArray("BGTaskSchedulerPermittedIdentifiers", [...refreshTasks, ...processingTasks]));
|
|
1436
|
+
stamps.push(plistArray("OneBackgroundRefreshTaskIdentifiers", refreshTasks));
|
|
1437
|
+
stamps.push(plistArray("OneBackgroundProcessingTaskIdentifiers", processingTasks));
|
|
1438
|
+
}
|
|
1439
|
+
const backgroundModes = [
|
|
1440
|
+
...app.pictureInPicture || app.audio?.background ? ["audio"] : [],
|
|
1441
|
+
...app.location?.background ? ["location"] : [],
|
|
1442
|
+
...refreshTasks.length ? ["fetch"] : [],
|
|
1443
|
+
...processingTasks.length ? ["processing"] : []
|
|
1444
|
+
];
|
|
1411
1445
|
if (backgroundModes.length) {
|
|
1412
1446
|
stamps.push(` <key>UIBackgroundModes</key>
|
|
1413
1447
|
<array>
|
|
@@ -1619,6 +1653,15 @@ ${schemes.map((scheme) => ` <data android:scheme="${scheme}" />`).joi
|
|
|
1619
1653
|
rendered = rendered.replace(/CURRENT_PROJECT_VERSION = [^;]+;/g, `CURRENT_PROJECT_VERSION = ${app.ios.buildNumber};`);
|
|
1620
1654
|
}
|
|
1621
1655
|
}
|
|
1656
|
+
if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj") && app.ios?.alternateIcons !== void 0) {
|
|
1657
|
+
const anchor = "ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;";
|
|
1658
|
+
if (!rendered.includes(anchor)) {
|
|
1659
|
+
throw new Error("[vxrn] prebuild template lost its primary app icon build setting");
|
|
1660
|
+
}
|
|
1661
|
+
const names = Object.keys(app.ios.alternateIcons).sort().join(" ");
|
|
1662
|
+
rendered = rendered.replaceAll(anchor, `${anchor}
|
|
1663
|
+
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "${names}";`);
|
|
1664
|
+
}
|
|
1622
1665
|
if (platform === "ios" && relativePath.endsWith("/Info.plist")) {
|
|
1623
1666
|
const usage = /* @__PURE__ */ new Map();
|
|
1624
1667
|
if (app.imagePicker?.camera !== void 0) {
|
|
@@ -1678,7 +1721,7 @@ ${schemes.map((scheme) => ` <data android:scheme="${scheme}" />`).joi
|
|
|
1678
1721
|
rendered = patchIosInfoPlistSceneManifest(rendered);
|
|
1679
1722
|
}
|
|
1680
1723
|
if (platform === "ios" && relativePath.endsWith("/AppDelegate.swift")) {
|
|
1681
|
-
rendered = patchIosAppDelegateSceneLifecycle(rendered, appName);
|
|
1724
|
+
rendered = patchIosAppDelegateSceneLifecycle(rendered, appName, !!app.ios?.backgroundTasks);
|
|
1682
1725
|
rendered = nativeProjectPatches.holdLaunchScreenOverRootView(rendered);
|
|
1683
1726
|
if (app.updates !== void 0) {
|
|
1684
1727
|
rendered = nativeProjectPatches.pointReleaseBundleURLAtOneUpdates(rendered);
|