vxrn 2.0.0-beta.99.1 → 2.6.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.
Files changed (210) hide show
  1. package/dist/backgroundComputation.mjs +145 -0
  2. package/dist/backgroundComputation.mjs.map +1 -0
  3. package/dist/backgroundComputation.native.js +163 -0
  4. package/dist/backgroundComputation.native.js.map +1 -0
  5. package/dist/backgroundComputationNative.mjs +16 -0
  6. package/dist/backgroundComputationNative.mjs.map +1 -0
  7. package/dist/backgroundComputationNative.native.js +18 -0
  8. package/dist/backgroundComputationNative.native.js.map +1 -0
  9. package/dist/config/getBaseViteConfigOnly.mjs +6 -10
  10. package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
  11. package/dist/config/getBaseViteConfigOnly.native.js +6 -10
  12. package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
  13. package/dist/config/getOptimizeDeps.mjs +2 -1
  14. package/dist/config/getOptimizeDeps.mjs.map +1 -1
  15. package/dist/config/getOptimizeDeps.native.js +2 -1
  16. package/dist/config/getOptimizeDeps.native.js.map +1 -1
  17. package/dist/config/getViteServerConfig.mjs +13 -0
  18. package/dist/config/getViteServerConfig.mjs.map +1 -1
  19. package/dist/config/getViteServerConfig.native.js +15 -1
  20. package/dist/config/getViteServerConfig.native.js.map +1 -1
  21. package/dist/constants/defaults.mjs +4 -0
  22. package/dist/constants/defaults.mjs.map +1 -1
  23. package/dist/constants/defaults.native.js +4 -0
  24. package/dist/constants/defaults.native.js.map +1 -1
  25. package/dist/exports/build.native.js +1 -1
  26. package/dist/exports/build.native.js.map +1 -1
  27. package/dist/exports/clean.native.js +1 -1
  28. package/dist/exports/clean.native.js.map +1 -1
  29. package/dist/exports/createServer.native.js +2 -2
  30. package/dist/exports/createServer.native.js.map +1 -1
  31. package/dist/exports/dev.mjs +3 -0
  32. package/dist/exports/dev.mjs.map +1 -1
  33. package/dist/exports/dev.native.js +6 -3
  34. package/dist/exports/dev.native.js.map +1 -1
  35. package/dist/exports/loadEnv.native.js +1 -1
  36. package/dist/exports/loadEnv.native.js.map +1 -1
  37. package/dist/exports/patch.native.js +1 -1
  38. package/dist/exports/patch.native.js.map +1 -1
  39. package/dist/exports/prebuild.mjs +0 -22
  40. package/dist/exports/prebuild.mjs.map +1 -1
  41. package/dist/exports/prebuild.native.js +1 -23
  42. package/dist/exports/prebuild.native.js.map +1 -1
  43. package/dist/exports/prebuildWithoutExpo.mjs +1116 -178
  44. package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
  45. package/dist/exports/prebuildWithoutExpo.native.js +1592 -243
  46. package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
  47. package/dist/exports/runAndroid.native.js +1 -1
  48. package/dist/exports/runAndroid.native.js.map +1 -1
  49. package/dist/exports/runIos.native.js +1 -1
  50. package/dist/exports/runIos.native.js.map +1 -1
  51. package/dist/exports/serve.native.js +1 -1
  52. package/dist/exports/serve.native.js.map +1 -1
  53. package/dist/exports/serveStaticAssets.native.js +1 -1
  54. package/dist/exports/serveStaticAssets.native.js.map +1 -1
  55. package/dist/index.js +4 -1
  56. package/dist/index.mjs +4 -1
  57. package/dist/index.native.js +4 -1
  58. package/dist/native-source-contract.mjs +3 -0
  59. package/dist/native-source-contract.native.js +3 -0
  60. package/dist/patches/builtInDepPatches.mjs +0 -13
  61. package/dist/patches/builtInDepPatches.mjs.map +1 -1
  62. package/dist/patches/builtInDepPatches.native.js +0 -13
  63. package/dist/patches/builtInDepPatches.native.js.map +1 -1
  64. package/dist/plugins/autoDepOptimizePlugin.mjs +3 -2
  65. package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
  66. package/dist/plugins/autoDepOptimizePlugin.native.js +6 -3
  67. package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
  68. package/dist/plugins/backgroundComputationPlugin.mjs +27 -0
  69. package/dist/plugins/backgroundComputationPlugin.mjs.map +1 -0
  70. package/dist/plugins/backgroundComputationPlugin.native.js +32 -0
  71. package/dist/plugins/backgroundComputationPlugin.native.js.map +1 -0
  72. package/dist/plugins/reactNativeCommonJsPlugin.native.js +3 -3
  73. package/dist/plugins/reactNativeCommonJsPlugin.native.js.map +1 -1
  74. package/dist/plugins/reactNativeDevAssetPlugin.mjs +2 -1
  75. package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
  76. package/dist/plugins/reactNativeDevAssetPlugin.native.js +3 -2
  77. package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
  78. package/dist/plugins/reactNativeDevServer.mjs +87 -24
  79. package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
  80. package/dist/plugins/reactNativeDevServer.native.js +162 -45
  81. package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
  82. package/dist/plugins/workletImportsPlugin.mjs +9 -30
  83. package/dist/plugins/workletImportsPlugin.mjs.map +1 -1
  84. package/dist/plugins/workletImportsPlugin.native.js +10 -35
  85. package/dist/plugins/workletImportsPlugin.native.js.map +1 -1
  86. package/dist/rn-commands/bundle/buildBundle.mjs +3 -3
  87. package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
  88. package/dist/rn-commands/bundle/buildBundle.native.js +3 -3
  89. package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
  90. package/dist/runtime/hmr-client.native.js +3 -7
  91. package/dist/runtime/hmr-client.native.js.map +1 -1
  92. package/dist/runtime/hmr-runtime.native.js +32 -40
  93. package/dist/runtime/hmr-runtime.native.js.map +1 -1
  94. package/dist/serve/node.native.js +2 -2
  95. package/dist/serve/node.native.js.map +1 -1
  96. package/dist/swift-package-id.mjs +3 -0
  97. package/dist/swift-package-id.native.js +3 -0
  98. package/dist/user-interface/index.native.js +6 -6
  99. package/dist/user-interface/index.native.js.map +1 -1
  100. package/dist/utils/compileNativeDevBytecode.mjs +93 -0
  101. package/dist/utils/compileNativeDevBytecode.mjs.map +1 -0
  102. package/dist/utils/compileNativeDevBytecode.native.js +98 -0
  103. package/dist/utils/compileNativeDevBytecode.native.js.map +1 -0
  104. package/dist/utils/createNativeDevEngine.mjs +227 -20
  105. package/dist/utils/createNativeDevEngine.mjs.map +1 -1
  106. package/dist/utils/createNativeDevEngine.native.js +249 -37
  107. package/dist/utils/createNativeDevEngine.native.js.map +1 -1
  108. package/dist/utils/execSync.native.js +1 -1
  109. package/dist/utils/execSync.native.js.map +1 -1
  110. package/dist/utils/getServerEntry.native.js +2 -2
  111. package/dist/utils/getServerEntry.native.js.map +1 -1
  112. package/dist/utils/nativeRun.mjs +32 -16
  113. package/dist/utils/nativeRun.mjs.map +1 -1
  114. package/dist/utils/nativeRun.native.js +43 -18
  115. package/dist/utils/nativeRun.native.js.map +1 -1
  116. package/dist/utils/nativeSourceContract.mjs +1823 -0
  117. package/dist/utils/nativeSourceContract.mjs.map +1 -0
  118. package/dist/utils/nativeSourceContract.native.js +2425 -0
  119. package/dist/utils/nativeSourceContract.native.js.map +1 -0
  120. package/dist/utils/patches.native.js +15 -24
  121. package/dist/utils/patches.native.js.map +1 -1
  122. package/dist/utils/printServerUrls.native.js +1 -1
  123. package/dist/utils/printServerUrls.native.js.map +1 -1
  124. package/dist/utils/scanDepsToOptimize.mjs +7 -1
  125. package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
  126. package/dist/utils/scanDepsToOptimize.native.js +27 -2
  127. package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
  128. package/dist/utils/swiftPackageId.mjs +31 -2
  129. package/dist/utils/swiftPackageId.mjs.map +1 -1
  130. package/dist/utils/swiftPackageId.native.js +50 -2
  131. package/dist/utils/swiftPackageId.native.js.map +1 -1
  132. package/dist/vxrn-vite-plugin.native.js +1 -1
  133. package/dist/vxrn-vite-plugin.native.js.map +1 -1
  134. package/expo-plugin.cjs +792 -2
  135. package/native-project-patches.cjs +201 -10
  136. package/package.json +34 -15
  137. package/src/backgroundComputation.ts +220 -0
  138. package/src/backgroundComputationNative.ts +23 -0
  139. package/src/config/getBaseViteConfigOnly.ts +8 -9
  140. package/src/config/getOptimizeDeps.ts +3 -1
  141. package/src/config/getViteServerConfig.ts +16 -0
  142. package/src/config/glbAssets.test.ts +228 -0
  143. package/src/constants/defaults.ts +6 -0
  144. package/src/exports/dev.ts +5 -1
  145. package/src/exports/expoPlugin.test.mjs +337 -15
  146. package/src/exports/prebuild.ts +0 -31
  147. package/src/exports/prebuildWithoutExpo.test.ts +1588 -48
  148. package/src/exports/prebuildWithoutExpo.ts +1573 -213
  149. package/src/index.ts +8 -0
  150. package/src/native-source-contract.ts +16 -0
  151. package/src/patches/builtInDepPatches.ts +0 -21
  152. package/src/plugins/autoDepOptimizePlugin.ts +7 -2
  153. package/src/plugins/backgroundComputationPlugin.test.ts +77 -0
  154. package/src/plugins/backgroundComputationPlugin.ts +29 -0
  155. package/src/plugins/reactNativeDevAssetPlugin.ts +5 -1
  156. package/src/plugins/reactNativeDevServer.test.ts +74 -0
  157. package/src/plugins/reactNativeDevServer.ts +145 -28
  158. package/src/plugins/rnCodegenPlugin.test.ts +30 -0
  159. package/src/plugins/workletImportsPlugin.ts +19 -37
  160. package/src/rn-commands/bundle/buildBundle.ts +5 -3
  161. package/src/swift-package-id.ts +1 -0
  162. package/src/utils/compileNativeDevBytecode.test.ts +168 -0
  163. package/src/utils/compileNativeDevBytecode.ts +117 -0
  164. package/src/utils/createNativeDevEngine.test.ts +643 -18
  165. package/src/utils/createNativeDevEngine.ts +278 -48
  166. package/src/utils/nativeRun.test.ts +125 -23
  167. package/src/utils/nativeRun.ts +51 -23
  168. package/src/utils/nativeSourceArtifacts.test.ts +39 -0
  169. package/src/utils/nativeSourceContract.test.ts +600 -0
  170. package/src/utils/nativeSourceContract.ts +1897 -0
  171. package/src/utils/scanDepsToOptimize.test.ts +80 -0
  172. package/src/utils/scanDepsToOptimize.ts +18 -7
  173. package/src/utils/swiftPackageId.ts +25 -1
  174. package/types/backgroundComputation.d.ts +28 -0
  175. package/types/backgroundComputation.d.ts.map +1 -0
  176. package/types/backgroundComputationNative.d.ts +2 -0
  177. package/types/backgroundComputationNative.d.ts.map +1 -0
  178. package/types/config/getBaseViteConfigOnly.d.ts.map +1 -1
  179. package/types/config/getOptimizeDeps.d.ts.map +1 -1
  180. package/types/config/getViteServerConfig.d.ts.map +1 -1
  181. package/types/constants/defaults.d.ts.map +1 -1
  182. package/types/exports/dev.d.ts.map +1 -1
  183. package/types/exports/prebuild.d.ts.map +1 -1
  184. package/types/exports/prebuildWithoutExpo.d.ts +6 -0
  185. package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
  186. package/types/index.d.ts +2 -0
  187. package/types/index.d.ts.map +1 -1
  188. package/types/native-source-contract.d.ts +2 -0
  189. package/types/native-source-contract.d.ts.map +1 -0
  190. package/types/patches/builtInDepPatches.d.ts.map +1 -1
  191. package/types/plugins/autoDepOptimizePlugin.d.ts.map +1 -1
  192. package/types/plugins/backgroundComputationPlugin.d.ts +3 -0
  193. package/types/plugins/backgroundComputationPlugin.d.ts.map +1 -0
  194. package/types/plugins/reactNativeDevAssetPlugin.d.ts.map +1 -1
  195. package/types/plugins/reactNativeDevServer.d.ts.map +1 -1
  196. package/types/plugins/workletImportsPlugin.d.ts.map +1 -1
  197. package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
  198. package/types/swift-package-id.d.ts +2 -0
  199. package/types/swift-package-id.d.ts.map +1 -0
  200. package/types/utils/compileNativeDevBytecode.d.ts +3 -0
  201. package/types/utils/compileNativeDevBytecode.d.ts.map +1 -0
  202. package/types/utils/createNativeDevEngine.d.ts +7 -22
  203. package/types/utils/createNativeDevEngine.d.ts.map +1 -1
  204. package/types/utils/nativeRun.d.ts.map +1 -1
  205. package/types/utils/nativeSourceContract.d.ts +121 -0
  206. package/types/utils/nativeSourceContract.d.ts.map +1 -0
  207. package/types/utils/scanDepsToOptimize.d.ts +1 -0
  208. package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
  209. package/types/utils/swiftPackageId.d.ts +1 -0
  210. package/types/utils/swiftPackageId.d.ts.map +1 -1
@@ -1,13 +1,19 @@
1
1
  import { execFileSync } from "child_process";
2
+ import { createHash } from "crypto";
2
3
  import module from "module";
3
4
  import path from "path";
4
5
  import { pathToFileURL } from "url";
5
6
  import { validateNativeApp } from "@vxrn/utils/nativeAppManifest";
6
7
  import FSExtra from "fs-extra";
7
8
  import sharp from "sharp";
8
- import { swiftPackageId } from "../utils/swiftPackageId.native.js";
9
+ import { swiftPackageDirectories } from "../utils/swiftPackageId.native.js";
9
10
 
10
- var nativeProjectPatches = module.createRequire(import.meta.url)("../../native-project-patches.cjs");
11
+ var requireVxrn = module.createRequire(import.meta.url);
12
+ var nativeProjectPatches = requireVxrn("../../native-project-patches.cjs");
13
+ var notificationsHost = nativeProjectPatches.ONE_NOTIFICATIONS;
14
+ var updatesHost = nativeProjectPatches.ONE_UPDATES;
15
+ var PORTRAIT_ORIENTATIONS = ["UIInterfaceOrientationPortrait", "UIInterfaceOrientationPortraitUpsideDown"];
16
+ var LANDSCAPE_ORIENTATIONS = ["UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight"];
11
17
  var validatePrebuildApp = validateNativeApp;
12
18
  var ANDROID_DENSITIES = {
13
19
  mdpi: 1,
@@ -19,7 +25,7 @@ var ANDROID_DENSITIES = {
19
25
  var IOS_BUNDLE_PLACEHOLDER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
20
26
  var ANDROID_PACKAGE_PLACEHOLDER = "com.helloworld";
21
27
  var ANDROID_PACKAGE_PATH = "com/helloworld";
22
- function patchIosBundlePhase(project) {
28
+ function patchIosBundlePhase(project, updatesRuntimeVersion) {
23
29
  var patchedBundlePhases = 0;
24
30
  var patchedProject = project.replace(/shellScript = ("(?:\\.|[^"\\])*");/g, function(assignment, serializedScript) {
25
31
  var script;
@@ -38,6 +44,12 @@ function patchIosBundlePhase(project) {
38
44
  if (!patched.includes("[vxrn/one] React Native now defaults CLI_PATH") || !patched.includes("[vxrn/one] use the hermes-engine pod") || !patched.includes("[vxrn/one] ensure patches are applied")) {
39
45
  throw new Error("[vxrn] failed to apply required iOS bundle phase patches");
40
46
  }
47
+ if (updatesRuntimeVersion !== void 0) {
48
+ patched = nativeProjectPatches.addEmbeddedUpdatesManifestToBundleReactNativeShellScript(patched, updatesRuntimeVersion);
49
+ if (!patched.includes("[vxrn/one] the embedded update manifest lands beside the release bundle")) {
50
+ throw new Error("[vxrn] failed to apply the iOS embedded updates manifest patch");
51
+ }
52
+ }
41
53
  patchedBundlePhases++;
42
54
  return `shellScript = ${JSON.stringify(patched)};`;
43
55
  });
@@ -64,21 +76,14 @@ import ReactAppDependencyProvider
64
76
  class SceneDelegate: UIResponder, UIWindowSceneDelegate {
65
77
  var window: UIWindow?
66
78
 
67
- var reactNativeDelegate: ReactNativeDelegate?
68
- var reactNativeFactory: RCTReactNativeFactory?
69
-
70
79
  func scene(
71
80
  _ scene: UIScene,
72
81
  willConnectTo session: UISceneSession,
73
82
  options connectionOptions: UIScene.ConnectionOptions
74
83
  ) {
75
84
  guard let windowScene = scene as? UIWindowScene else { return }
76
- let delegate = ReactNativeDelegate()
77
- let factory = RCTReactNativeFactory(delegate: delegate)
78
- delegate.dependencyProvider = RCTAppDependencyProvider()
79
-
80
- reactNativeDelegate = delegate
81
- reactNativeFactory = factory
85
+ guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
86
+ let factory = appDelegate.reactNativeFactory else { return }
82
87
 
83
88
  let window = UIWindow(windowScene: windowScene)
84
89
  self.window = window
@@ -154,7 +159,7 @@ function patchIosInfoPlistSceneManifest(rendered) {
154
159
  </dict>
155
160
  ${anchor}`);
156
161
  }
157
- function patchIosAppDelegateSceneLifecycle(rendered, appName) {
162
+ function patchIosAppDelegateSceneLifecycle(rendered, appName, backgroundTasks, appIntents) {
158
163
  var anchor = `@main
159
164
  class AppDelegate: UIResponder, UIApplicationDelegate {
160
165
  var window: UIWindow?
@@ -189,38 +194,49 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
189
194
  }
190
195
  return rendered.replace(anchor, `@main
191
196
  class AppDelegate: UIResponder, UIApplicationDelegate {
197
+ var reactNativeDelegate: ReactNativeDelegate?
198
+ var reactNativeFactory: RCTReactNativeFactory?
199
+
192
200
  func application(
193
201
  _ application: UIApplication,
194
202
  didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
195
203
  ) -> Bool {
196
- true
197
- }
198
-
199
- // remote push answers land here; the notifications module observes the
200
- // forward. inert unless something calls registerForRemoteNotifications.
201
- func application(
202
- _ application: UIApplication,
203
- didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
204
- ) {
205
- NotificationCenter.default.post(
206
- name: NSNotification.Name("OneNativePushTokenDidRegister"),
207
- object: nil,
208
- userInfo: ["deviceToken": deviceToken]
209
- )
210
- }
211
-
212
- func application(
213
- _ application: UIApplication,
214
- didFailToRegisterForRemoteNotificationsWithError error: Error
215
- ) {
216
- NotificationCenter.default.post(
217
- name: NSNotification.Name("OneNativePushTokenDidFail"),
218
- object: nil,
219
- userInfo: ["error": error.localizedDescription]
220
- )
204
+ let delegate = ReactNativeDelegate()
205
+ let factory = RCTReactNativeFactory(delegate: delegate)
206
+ delegate.dependencyProvider = RCTAppDependencyProvider()
207
+ reactNativeDelegate = delegate
208
+ reactNativeFactory = factory
209
+ ${backgroundTasks ? ` OneBackgroundTasksRegisterHost(factory, launchOptions)
210
+ ` : ""}${appIntents ? ` OneAppIntentsRegisterHost(factory, launchOptions)
211
+ ` : ""} return true
221
212
  }
222
213
  }`);
223
214
  }
215
+ var ONE_BRIDGING_HEADER_NAME = "One-Bridging-Header.h";
216
+ function renderOneBridgingHeader(app) {
217
+ var _app_ios, _app_ios1;
218
+ var imports = [nativeProjectPatches.ONE_LAUNCH_SCREEN.bridgingHeaderImport];
219
+ if (app.updates !== void 0) imports.push(updatesHost.bridgingHeaderImport);
220
+ if (((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.backgroundTasks) !== void 0) imports.push("#import \"OneBackgroundTasksBridge.h\"");
221
+ if (((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.appIntents) !== void 0) imports.push("#import \"OneAppIntentsBridge.h\"");
222
+ return `// generated by one prebuild: exposes One's c entry points to AppDelegate
223
+ // without importing the One module.
224
+ ${imports.join("\n")}
225
+ `;
226
+ }
227
+ function generateOneBridgingHeader(dest, app) {
228
+ FSExtra.writeFileSync(path.join(dest, app.name, ONE_BRIDGING_HEADER_NAME), renderOneBridgingHeader(app));
229
+ }
230
+ function patchIosPbxprojOneBridgingHeader(project, appName) {
231
+ var anchor = `INFOPLIST_FILE = ${appName}/Info.plist;`;
232
+ var setting = `SWIFT_OBJC_BRIDGING_HEADER = "${appName}/${ONE_BRIDGING_HEADER_NAME}";`;
233
+ var occurrences = project.split(anchor).length - 1;
234
+ if (occurrences !== 2) {
235
+ throw new Error("[vxrn] prebuild template project.pbxproj changed shape: cannot point the app target at the One bridging header");
236
+ }
237
+ return project.split(anchor).join(`${anchor}
238
+ ${setting}`);
239
+ }
224
240
  function patchIosPbxprojSceneDelegate(rendered, appName) {
225
241
  var edits = [
226
242
  ["/* AppDelegate.swift in Sources */ = {isa = PBXBuildFile;", ` ${SCENE_DELEGATE_BUILD_FILE_ID} /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ${SCENE_DELEGATE_FILE_REF_ID} /* SceneDelegate.swift */; };`],
@@ -255,7 +271,209 @@ function patchIosPbxprojSceneDelegate(rendered, appName) {
255
271
  }
256
272
  return patched;
257
273
  }
258
- function patchIosPbxprojPushEntitlements(rendered, appName) {
274
+ function patchIosPbxprojAppIntents(rendered, appName) {
275
+ var name = "OneAppIntents.swift";
276
+ var fileRef = pbxprojId("one-app-intents-file");
277
+ var buildFile = pbxprojId("one-app-intents-build");
278
+ var edits = [
279
+ ["/* AppDelegate.swift in Sources */ = {isa = PBXBuildFile;", ` ${buildFile} /* ${name} in Sources */ = {isa = PBXBuildFile; fileRef = ${fileRef} /* ${name} */; };`],
280
+ ["/* AppDelegate.swift */ = {isa = PBXFileReference;", ` ${fileRef} /* ${name} */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ${name}; path = ${appName}/${name}; sourceTree = "<group>"; };`],
281
+ ["/* AppDelegate.swift */,", ` ${fileRef} /* ${name} */,`],
282
+ ["/* AppDelegate.swift in Sources */,", ` ${buildFile} /* ${name} in Sources */,`]
283
+ ];
284
+ var patched = rendered;
285
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
286
+ try {
287
+ for (var _iterator = edits[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
288
+ var [anchor, insertion] = _step.value;
289
+ var next = insertAfterLine(patched, anchor, insertion);
290
+ if (next === patched) {
291
+ throw new Error(`[vxrn] prebuild template project.pbxproj lost its AppDelegate.swift anchor (${anchor})`);
292
+ }
293
+ patched = next;
294
+ }
295
+ } catch (err) {
296
+ _didIteratorError = true;
297
+ _iteratorError = err;
298
+ } finally {
299
+ try {
300
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
301
+ _iterator.return();
302
+ }
303
+ } finally {
304
+ if (_didIteratorError) {
305
+ throw _iteratorError;
306
+ }
307
+ }
308
+ }
309
+ return patched;
310
+ }
311
+ function swiftLiteral(value) {
312
+ return JSON.stringify(value).replace(/\\u([0-9a-fA-F]{4})/g, function(_match, hex) {
313
+ return `\\u{${hex}}`;
314
+ });
315
+ }
316
+ function swiftShortcutPhrase(value) {
317
+ return `"${value.split("{app}").map(function(part) {
318
+ return swiftLiteral(part).slice(1, -1);
319
+ }).join("\\(.applicationName)")}"`;
320
+ }
321
+ function renderIosAppIntentsSwift(actions) {
322
+ var types = actions.map(function(action, index) {
323
+ var summaryTitle = swiftLiteral(action.title).slice(1, -1);
324
+ var text = action.textParameterTitle === void 0 ? "" : `
325
+ @Parameter(title: ${swiftLiteral(action.textParameterTitle)}) var text: String
326
+
327
+ static var parameterSummary: some ParameterSummary {
328
+ Summary("${summaryTitle} \\(\\.$text)")
329
+ }
330
+ `;
331
+ return `struct OneAppIntent${index}: AppIntent {
332
+ static let title: LocalizedStringResource = ${swiftLiteral(action.title)}
333
+ ${text}
334
+ func perform() async throws -> some IntentResult & ReturnsValue<String> {
335
+ let result = try await oneAppIntentsRun(${swiftLiteral(action.id)}, ${text ? "text" : "nil"})
336
+ return .result(value: result)
337
+ }
338
+ }`;
339
+ });
340
+ var shortcuts = actions.map(function(action, index) {
341
+ return ` AppShortcut(
342
+ intent: OneAppIntent${index}(),
343
+ phrases: [${swiftShortcutPhrase(action.shortcutPhrase)}],
344
+ shortTitle: ${swiftLiteral(action.title)},
345
+ systemImageName: "bolt.fill"
346
+ )`;
347
+ }).join("\n");
348
+ return `import AppIntents
349
+ import Foundation
350
+
351
+ private func oneAppIntentsRun(_ identifier: String, _ text: String?) async throws -> String {
352
+ try await withCheckedThrowingContinuation { continuation in
353
+ OneAppIntentsPerform(identifier, text) { result, error in
354
+ if let error { continuation.resume(throwing: error) }
355
+ else if let result { continuation.resume(returning: result) }
356
+ else { continuation.resume(throwing: NSError(domain: "OneAppIntents", code: 3)) }
357
+ }
358
+ }
359
+ }
360
+
361
+ ${types.join("\n\n")}
362
+
363
+ struct OneAppShortcuts: AppShortcutsProvider {
364
+ static var appShortcuts: [AppShortcut] {
365
+ ${shortcuts}
366
+ }
367
+ }
368
+ `;
369
+ }
370
+ function fontFileName(font) {
371
+ return path.basename(font);
372
+ }
373
+ function pbxprojId(seed) {
374
+ return createHash("sha1").update(seed).digest("hex").slice(0, 24).toUpperCase();
375
+ }
376
+ var GOOGLE_SERVICES_PLIST = "GoogleService-Info.plist";
377
+ var GOOGLE_SERVICES_VERSION = "4.4.4";
378
+ function iosResourceFiles(app) {
379
+ var _app_fonts;
380
+ var _app_ios;
381
+ return [...((_app_fonts = app.fonts) !== null && _app_fonts !== void 0 ? _app_fonts : []).map(fontFileName), ...((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.googleServicesFile) ? [GOOGLE_SERVICES_PLIST] : []];
382
+ }
383
+ function patchIosPbxprojResources(rendered, appName, names) {
384
+ var patched = rendered;
385
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
386
+ try {
387
+ for (var _iterator = names[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
388
+ var name = _step.value;
389
+ var fileRef = pbxprojId(`one-resource-file:${name}`);
390
+ var buildFile = pbxprojId(`one-resource-build:${name}`);
391
+ var fileType = name.endsWith(".plist") ? "text.plist.xml" : "file";
392
+ var edits = [
393
+ ["/* Images.xcassets in Resources */ = {isa = PBXBuildFile;", ` ${buildFile} /* ${name} in Resources */ = {isa = PBXBuildFile; fileRef = ${fileRef} /* ${name} */; };`],
394
+ ["/* Images.xcassets */ = {isa = PBXFileReference;", ` ${fileRef} /* ${name} */ = {isa = PBXFileReference; lastKnownFileType = ${fileType}; name = ${name}; path = ${appName}/${name}; sourceTree = "<group>"; };`],
395
+ ["/* Images.xcassets */,", ` ${fileRef} /* ${name} */,`],
396
+ ["/* Images.xcassets in Resources */,", ` ${buildFile} /* ${name} in Resources */,`]
397
+ ];
398
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
399
+ try {
400
+ for (var _iterator1 = edits[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
401
+ var [anchor, insertion] = _step1.value;
402
+ var next = insertAfterLine(patched, anchor, insertion);
403
+ if (next === patched) {
404
+ throw new Error(`[vxrn] prebuild template project.pbxproj lost its Images.xcassets anchor (${anchor})`);
405
+ }
406
+ patched = next;
407
+ }
408
+ } catch (err) {
409
+ _didIteratorError1 = true;
410
+ _iteratorError1 = err;
411
+ } finally {
412
+ try {
413
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
414
+ _iterator1.return();
415
+ }
416
+ } finally {
417
+ if (_didIteratorError1) {
418
+ throw _iteratorError1;
419
+ }
420
+ }
421
+ }
422
+ }
423
+ } catch (err) {
424
+ _didIteratorError = true;
425
+ _iteratorError = err;
426
+ } finally {
427
+ try {
428
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
429
+ _iterator.return();
430
+ }
431
+ } finally {
432
+ if (_didIteratorError) {
433
+ throw _iteratorError;
434
+ }
435
+ }
436
+ }
437
+ return patched;
438
+ }
439
+ function copyAppResources(param) {
440
+ var { root, dest, platform, app } = param;
441
+ var _app_fonts;
442
+ var _app_ios, _app_android;
443
+ var copies = ((_app_fonts = app.fonts) !== null && _app_fonts !== void 0 ? _app_fonts : []).map(function(font) {
444
+ return [font, platform === "ios" ? path.join(dest, app.name, fontFileName(font)) : path.join(dest, "app", "src", "main", "assets", "fonts", fontFileName(font))];
445
+ });
446
+ var googleServices = platform === "ios" ? (_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.googleServicesFile : (_app_android = app.android) === null || _app_android === void 0 ? void 0 : _app_android.googleServicesFile;
447
+ if (googleServices) {
448
+ copies.push([googleServices, platform === "ios" ? path.join(dest, app.name, GOOGLE_SERVICES_PLIST) : path.join(dest, "app", "google-services.json")]);
449
+ }
450
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
451
+ try {
452
+ for (var _iterator = copies[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
453
+ var [file, target] = _step.value;
454
+ var source = path.resolve(root, file);
455
+ if (!FSExtra.existsSync(source)) {
456
+ throw new Error(`[vxrn] native.app names ${file}, which does not exist`);
457
+ }
458
+ FSExtra.mkdirSync(path.dirname(target), { recursive: true });
459
+ FSExtra.copyFileSync(source, target);
460
+ }
461
+ } catch (err) {
462
+ _didIteratorError = true;
463
+ _iteratorError = err;
464
+ } finally {
465
+ try {
466
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
467
+ _iterator.return();
468
+ }
469
+ } finally {
470
+ if (_didIteratorError) {
471
+ throw _iteratorError;
472
+ }
473
+ }
474
+ }
475
+ }
476
+ function patchIosPbxprojAppEntitlements(rendered, appName) {
259
477
  var edits = [["/* AppDelegate.swift */ = {isa = PBXFileReference;", ` ${PUSH_ENTITLEMENTS_FILE_REF_ID} /* ${appName}.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ${appName}.entitlements; path = ${appName}/${appName}.entitlements; sourceTree = "<group>"; };`], ["/* AppDelegate.swift */,", ` ${PUSH_ENTITLEMENTS_FILE_REF_ID} /* ${appName}.entitlements */,`]];
260
478
  var patched = rendered;
261
479
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
@@ -289,17 +507,118 @@ function patchIosPbxprojPushEntitlements(rendered, appName) {
289
507
  return patched.split(setting).join(`${setting}
290
508
  CODE_SIGN_ENTITLEMENTS = ${appName}/${appName}.entitlements;`);
291
509
  }
292
- function renderPushEntitlements() {
510
+ function renderPlistValue(value, indent) {
511
+ if (typeof value === "string") return `${indent}<string>${escapeXml(value)}</string>`;
512
+ if (typeof value === "boolean") return `${indent}<${value}/>`;
513
+ if (typeof value === "number") {
514
+ return Number.isInteger(value) ? `${indent}<integer>${value}</integer>` : `${indent}<real>${value}</real>`;
515
+ }
516
+ if (Array.isArray(value)) {
517
+ return `${indent}<array>
518
+ ${value.map(function(item) {
519
+ return renderPlistValue(item, `${indent} `);
520
+ }).join("\n")}
521
+ ${indent}</array>`;
522
+ }
523
+ return `${indent}<dict>
524
+ ${renderPlistEntries(value, `${indent} `)}
525
+ ${indent}</dict>`;
526
+ }
527
+ function renderPlistEntries(entries, indent) {
528
+ return Object.entries(entries).map(function(param) {
529
+ var [key, value] = param;
530
+ return `${indent}<key>${escapeXml(key)}</key>
531
+ ${renderPlistValue(value, indent)}`;
532
+ }).join("\n");
533
+ }
534
+ function appEntitlements(app) {
535
+ var _ref;
536
+ var _app_notifications, _app_ios_widgets, _app_ios, _app_ios1, _app_ios_associatedDomains, _app_ios2, _app_ios3, _app_ios4, _app_ios5;
537
+ var modeled = {};
538
+ if (((_app_notifications = app.notifications) === null || _app_notifications === void 0 ? void 0 : _app_notifications.push) === true || ((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : (_app_ios_widgets = _app_ios.widgets) === null || _app_ios_widgets === void 0 ? void 0 : _app_ios_widgets.pushNotifications)) {
539
+ var _ref1;
540
+ var _app_notifications1;
541
+ modeled["aps-environment"] = (_ref1 = (_app_notifications1 = app.notifications) === null || _app_notifications1 === void 0 ? void 0 : _app_notifications1.apsEnvironment) !== null && _ref1 !== void 0 ? _ref1 : notificationsHost.apsEnvironment;
542
+ }
543
+ if ((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.widgets) {
544
+ modeled["com.apple.security.application-groups"] = [app.ios.widgets.appGroup];
545
+ }
546
+ if ((_app_ios2 = app.ios) === null || _app_ios2 === void 0 ? void 0 : (_app_ios_associatedDomains = _app_ios2.associatedDomains) === null || _app_ios_associatedDomains === void 0 ? void 0 : _app_ios_associatedDomains.length) {
547
+ modeled["com.apple.developer.associated-domains"] = app.ios.associatedDomains;
548
+ }
549
+ if ((_app_ios3 = app.ios) === null || _app_ios3 === void 0 ? void 0 : _app_ios3.usesAppleSignIn) {
550
+ modeled["com.apple.developer.applesignin"] = ["Default"];
551
+ }
552
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
553
+ try {
554
+ for (var _iterator = Object.keys((_ref = (_app_ios4 = app.ios) === null || _app_ios4 === void 0 ? void 0 : _app_ios4.entitlements) !== null && _ref !== void 0 ? _ref : {})[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
555
+ var key = _step.value;
556
+ if (key in modeled) {
557
+ throw new Error(`[vxrn] native.app.ios.entitlements sets ${key}, which native.app already writes: use its field`);
558
+ }
559
+ }
560
+ } catch (err) {
561
+ _didIteratorError = true;
562
+ _iteratorError = err;
563
+ } finally {
564
+ try {
565
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
566
+ _iterator.return();
567
+ }
568
+ } finally {
569
+ if (_didIteratorError) {
570
+ throw _iteratorError;
571
+ }
572
+ }
573
+ }
574
+ return {
575
+ ...modeled,
576
+ ...(_app_ios5 = app.ios) === null || _app_ios5 === void 0 ? void 0 : _app_ios5.entitlements
577
+ };
578
+ }
579
+ function renderEntitlements(entries) {
293
580
  return `<?xml version="1.0" encoding="UTF-8"?>
294
581
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
295
582
  <plist version="1.0">
296
583
  <dict>
297
- <key>aps-environment</key>
298
- <string>development</string>
584
+ ${renderPlistEntries(entries, " ")}
299
585
  </dict>
300
586
  </plist>
301
587
  `;
302
588
  }
589
+ function patchAndroidMainApplicationUpdatesHost(rendered) {
590
+ var anchor = "import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost";
591
+ if (!rendered.includes(anchor)) {
592
+ throw new Error("[vxrn] prebuild template MainApplication.kt changed shape: cannot point the ReactHost at One.Updates");
593
+ }
594
+ return rendered.replace(anchor, "import com.margelo.nitro.one.OneUpdatesReactHost.getDefaultReactHost");
595
+ }
596
+ function escapeGradleString(value) {
597
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
598
+ }
599
+ function patchAndroidBuildGradleUpdatesManifest(rendered, runtimeVersion) {
600
+ var anchor = " autolinkLibrariesWithApp()\n}";
601
+ if (!rendered.includes(anchor)) {
602
+ throw new Error("[vxrn] cannot stamp the embedded updates manifest: expected the replaced react block in app/build.gradle");
603
+ }
604
+ var snippet = `${anchor}
605
+
606
+ // [vxrn/one] the embedded update manifest lands beside the release bundle
607
+ tasks.matching { it.name.startsWith("createBundle") && it.name.endsWith("JsAndAssets") }.configureEach { bundleTask ->
608
+ // capture the output directory provider at configuration time, so the
609
+ // action below holds no task reference at execution time.
610
+ def bundleDir = bundleTask.jsBundleDir
611
+ bundleTask.doLast {
612
+ def manifestFile = new File(bundleDir.get().asFile, "one-updates-embedded.json")
613
+ manifestFile.text = groovy.json.JsonOutput.toJson([
614
+ id: java.util.UUID.randomUUID().toString(),
615
+ createdAt: java.time.Instant.now().toString(),
616
+ runtimeVersion: "${escapeGradleString(runtimeVersion)}",
617
+ ])
618
+ }
619
+ }`;
620
+ return rendered.replace(anchor, snippet);
621
+ }
303
622
  function patchIosPbxprojWidgets(project, app) {
304
623
  var name = app.name;
305
624
  var bundleId = app.ios.bundleId;
@@ -331,7 +650,7 @@ function patchIosPbxprojWidgets(project, app) {
331
650
  bridgeObjcBuild: "A10000000000000000000018",
332
651
  embedBuild: "A10000000000000000000019"
333
652
  };
334
- var insert = function(anchor, value) {
653
+ var insert = function insert2(anchor, value) {
335
654
  if (!project.includes(anchor)) throw new Error(`[vxrn] widget target template anchor missing: ${anchor}`);
336
655
  project = project.replace(anchor, `${value}
337
656
  ${anchor}`);
@@ -367,14 +686,14 @@ ${anchor}`);
367
686
  ${ids.dependency} /* PBXTargetDependency */ = {isa = PBXTargetDependency; target = ${ids.target} /* OneWidgets */; targetProxy = ${ids.proxy} /* PBXContainerItemProxy */; };
368
687
  /* End PBXTargetDependency section */
369
688
  `);
370
- var config = function(id, mode) {
689
+ var config = function config2(id, mode) {
371
690
  var _app_ios, _app_ios1;
372
691
  return ` ${id} /* ${mode} */ = {isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = OneWidgets/OneWidgets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = ${((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.buildNumber) || "1"}; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OneWidgets/WidgetInfo.plist; IPHONEOS_DEPLOYMENT_TARGET = ${deploymentTarget}; MARKETING_VERSION = "${app.version || "1.0"}"; PRODUCT_BUNDLE_IDENTIFIER = ${bundleId}.widgets; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "${((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.tablet) ? "1,2" : "1"}"; }; name = ${mode}; };`;
373
692
  };
374
693
  insert("/* End XCBuildConfiguration section */", `${config(ids.debug, "Debug")}
375
694
  ${config(ids.release, "Release")}`);
376
695
  insert("/* End XCConfigurationList section */", ` ${ids.config} /* Build configuration list for PBXNativeTarget "OneWidgets" */ = {isa = XCConfigurationList; buildConfigurations = (${ids.debug} /* Debug */, ${ids.release} /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; };`);
377
- var one = function(anchor, value) {
696
+ var one = function one2(anchor, value) {
378
697
  if (!project.includes(anchor)) throw new Error(`[vxrn] widget target template anchor missing: ${anchor}`);
379
698
  project = project.replace(anchor, `${anchor}
380
699
  ${value}`);
@@ -401,16 +720,22 @@ ${value}`);
401
720
  return project;
402
721
  }
403
722
  function generateSceneDelegate(args) {
404
- var _app_notifications, _app_ios;
723
+ var _app_ios;
405
724
  var { dest, platform, app } = args;
406
725
  if (platform !== "ios") return;
407
726
  FSExtra.writeFileSync(path.join(dest, app.name, "SceneDelegate.swift"), renderSceneDelegateSwift(app.name));
408
- if (((_app_notifications = app.notifications) === null || _app_notifications === void 0 ? void 0 : _app_notifications.push) === true && !((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.widgets)) {
409
- FSExtra.writeFileSync(path.join(dest, app.name, `${app.name}.entitlements`), renderPushEntitlements());
727
+ var entitlements = appEntitlements(app);
728
+ if (Object.keys(entitlements).length && !((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.widgets)) {
729
+ FSExtra.writeFileSync(path.join(dest, app.name, `${app.name}.entitlements`), renderEntitlements(entitlements));
410
730
  }
411
731
  }
732
+ function generateIosAppIntents(dest, platform, app) {
733
+ var _app_ios;
734
+ if (platform !== "ios" || !((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.appIntents)) return;
735
+ FSExtra.writeFileSync(path.join(dest, app.name, "OneAppIntents.swift"), renderIosAppIntentsSwift(app.ios.appIntents.actions));
736
+ }
412
737
  function generateIosWidgets(dest, app) {
413
- var _app_ios, _app_notifications, _app_ios1;
738
+ var _app_ios, _app_ios1;
414
739
  var widgets = (_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.widgets;
415
740
  if (!widgets) return;
416
741
  var appDir = path.join(dest, app.name);
@@ -420,7 +745,7 @@ function generateIosWidgets(dest, app) {
420
745
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
421
746
  <plist version="1.0"><dict><key>com.apple.security.application-groups</key><array><string>${escapeXml(widgets.appGroup)}</string></array></dict></plist>
422
747
  `;
423
- FSExtra.writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), widgets.pushNotifications || ((_app_notifications = app.notifications) === null || _app_notifications === void 0 ? void 0 : _app_notifications.push) ? entitlements.replace("</dict></plist>", "<key>aps-environment</key><string>development</string></dict></plist>") : entitlements);
748
+ FSExtra.writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), renderEntitlements(appEntitlements(app)));
424
749
  FSExtra.writeFileSync(path.join(extensionDir, "OneWidgets.entitlements"), entitlements);
425
750
  FSExtra.writeFileSync(path.join(extensionDir, "WidgetInfo.plist"), `<?xml version="1.0" encoding="UTF-8"?>
426
751
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -928,31 +1253,110 @@ class OneWidgetsBridge: RCTEventEmitter {
928
1253
  }
929
1254
  `);
930
1255
  }
1256
+ var IPAD_APP_ICON_SIZES = [
1257
+ ["20x20", ["1x", "2x"]],
1258
+ ["29x29", ["1x", "2x"]],
1259
+ ["40x40", ["1x", "2x"]],
1260
+ ["76x76", ["1x", "2x"]],
1261
+ ["83.5x83.5", ["2x"]]
1262
+ ];
931
1263
  async function generateAppIcons(args) {
932
1264
  var { root, dest, platform, app } = args;
933
1265
  if (!app.icon) return;
934
- var source = path.resolve(root, app.icon.source);
935
- if (!FSExtra.existsSync(source)) {
936
- throw new Error(`[vxrn] native.app.icon source does not exist: ${source}`);
937
- }
938
- var metadata = await sharp(source).metadata();
939
- if (metadata.width === void 0 || metadata.height === void 0 || metadata.width !== metadata.height || metadata.width < 1024) {
940
- throw new Error("[vxrn] native.app.icon source must be a square image at least 1024px wide");
941
- }
942
1266
  if (platform === "ios") {
943
- var iconDir = path.join(dest, app.name, "Images.xcassets", "AppIcon.appiconset");
944
- var contentsPath = path.join(iconDir, "Contents.json");
945
- var contents = JSON.parse(FSExtra.readFileSync(contentsPath, "utf8"));
1267
+ var _ref;
1268
+ var _app_ios;
1269
+ var assetsDir = path.join(dest, app.name, "Images.xcassets");
1270
+ var template = JSON.parse(FSExtra.readFileSync(path.join(assetsDir, "AppIcon.appiconset", "Contents.json"), "utf8"));
1271
+ var icons = [["AppIcon", app.icon], ...Object.entries((_ref = (_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.alternateIcons) !== null && _ref !== void 0 ? _ref : {})];
946
1272
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
947
1273
  try {
948
- for (var _iterator = contents.images[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
949
- var image = _step.value;
950
- var points = Number.parseFloat(image.size.split("x")[0]);
951
- var scale = Number.parseInt(image.scale, 10);
952
- var pixels = points * scale;
953
- var filename = image.idiom === "ios-marketing" ? "icon-1024.png" : `icon-${points}@${image.scale}.png`;
954
- image.filename = filename;
955
- await sharp(source).rotate().resize(pixels, pixels, { fit: "cover" }).flatten({ background: app.icon.backgroundColor }).png().toFile(path.join(iconDir, filename));
1274
+ for (var _iterator = icons[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
1275
+ var [name, icon] = _step.value;
1276
+ var _app_ios1;
1277
+ var source = path.resolve(root, icon.source);
1278
+ if (!FSExtra.existsSync(source)) {
1279
+ throw new Error(`[vxrn] native.app icon source does not exist: ${source}`);
1280
+ }
1281
+ var metadata = await sharp(source).metadata();
1282
+ if (metadata.width !== metadata.height || metadata.width === void 0 || metadata.width < 1024) {
1283
+ throw new Error(`[vxrn] native.app icon source must be a square image at least 1024px wide: ${source}`);
1284
+ }
1285
+ var iconDir = path.join(assetsDir, `${name}.appiconset`);
1286
+ FSExtra.mkdirSync(iconDir, { recursive: true });
1287
+ var contents = structuredClone(template);
1288
+ if ((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.tablet) {
1289
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
1290
+ try {
1291
+ for (var _iterator1 = IPAD_APP_ICON_SIZES[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
1292
+ var [size, scales] = _step1.value;
1293
+ var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1294
+ try {
1295
+ for (var _iterator2 = scales[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
1296
+ var scale = _step2.value;
1297
+ contents.images.push({
1298
+ idiom: "ipad",
1299
+ scale,
1300
+ size
1301
+ });
1302
+ }
1303
+ } catch (err) {
1304
+ _didIteratorError2 = true;
1305
+ _iteratorError2 = err;
1306
+ } finally {
1307
+ try {
1308
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
1309
+ _iterator2.return();
1310
+ }
1311
+ } finally {
1312
+ if (_didIteratorError2) {
1313
+ throw _iteratorError2;
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+ } catch (err) {
1319
+ _didIteratorError1 = true;
1320
+ _iteratorError1 = err;
1321
+ } finally {
1322
+ try {
1323
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1324
+ _iterator1.return();
1325
+ }
1326
+ } finally {
1327
+ if (_didIteratorError1) {
1328
+ throw _iteratorError1;
1329
+ }
1330
+ }
1331
+ }
1332
+ }
1333
+ var _iteratorNormalCompletion3 = true, _didIteratorError3 = false, _iteratorError3 = void 0;
1334
+ try {
1335
+ for (var _iterator3 = contents.images[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
1336
+ var image = _step3.value;
1337
+ var points = Number.parseFloat(image.size.split("x")[0]);
1338
+ var scale1 = Number.parseInt(image.scale, 10);
1339
+ var pixels = points * scale1;
1340
+ var filename = image.idiom === "ios-marketing" ? "icon-1024.png" : `icon-${points}@${image.scale}.png`;
1341
+ image.filename = filename;
1342
+ await sharp(source).rotate().resize(pixels, pixels, { fit: "cover" }).flatten({ background: icon.backgroundColor }).png().toFile(path.join(iconDir, filename));
1343
+ }
1344
+ } catch (err) {
1345
+ _didIteratorError3 = true;
1346
+ _iteratorError3 = err;
1347
+ } finally {
1348
+ try {
1349
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
1350
+ _iterator3.return();
1351
+ }
1352
+ } finally {
1353
+ if (_didIteratorError3) {
1354
+ throw _iteratorError3;
1355
+ }
1356
+ }
1357
+ }
1358
+ FSExtra.writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify(contents, null, 2)}
1359
+ `);
956
1360
  }
957
1361
  } catch (err) {
958
1362
  _didIteratorError = true;
@@ -968,73 +1372,273 @@ async function generateAppIcons(args) {
968
1372
  }
969
1373
  }
970
1374
  }
971
- FSExtra.writeFileSync(contentsPath, `${JSON.stringify(contents, null, 2)}
972
- `);
973
1375
  return;
974
1376
  }
975
- var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
1377
+ var source1 = path.resolve(root, app.icon.source);
1378
+ if (!FSExtra.existsSync(source1)) {
1379
+ throw new Error(`[vxrn] native.app.icon source does not exist: ${source1}`);
1380
+ }
1381
+ var metadata1 = await sharp(source1).metadata();
1382
+ if (metadata1.width !== metadata1.height || metadata1.width === void 0 || metadata1.width < 1024) {
1383
+ throw new Error("[vxrn] native.app.icon source must be a square image at least 1024px wide");
1384
+ }
1385
+ var _iteratorNormalCompletion4 = true, _didIteratorError4 = false, _iteratorError4 = void 0;
976
1386
  try {
977
- for (var _iterator1 = Object.entries(ANDROID_DENSITIES)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
978
- var [density, multiplier] = _step1.value;
1387
+ for (var _iterator4 = Object.entries(ANDROID_DENSITIES)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
1388
+ var [density, multiplier] = _step4.value;
979
1389
  var pixels1 = 48 * multiplier;
980
1390
  var iconDir1 = path.join(dest, "app", "src", "main", "res", `mipmap-${density}`);
981
1391
  for (var _i = 0, _iter = ["ic_launcher.png", "ic_launcher_round.png"]; _i < _iter.length; _i++) {
982
1392
  var filename1 = _iter[_i];
983
- await sharp(source).rotate().resize(pixels1, pixels1, { fit: "cover" }).flatten({ background: app.icon.backgroundColor }).png().toFile(path.join(iconDir1, filename1));
1393
+ await sharp(source1).rotate().resize(pixels1, pixels1, { fit: "cover" }).flatten({ background: app.icon.backgroundColor }).png().toFile(path.join(iconDir1, filename1));
984
1394
  }
985
1395
  }
986
1396
  } catch (err) {
987
- _didIteratorError1 = true;
988
- _iteratorError1 = err;
1397
+ _didIteratorError4 = true;
1398
+ _iteratorError4 = err;
989
1399
  } finally {
990
1400
  try {
991
- if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
992
- _iterator1.return();
1401
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
1402
+ _iterator4.return();
993
1403
  }
994
1404
  } finally {
995
- if (_didIteratorError1) {
996
- throw _iteratorError1;
1405
+ if (_didIteratorError4) {
1406
+ throw _iteratorError4;
997
1407
  }
998
1408
  }
999
1409
  }
1000
1410
  }
1001
- async function generateSplashScreen(args) {
1002
- var _app_splash_width;
1003
- var { root, dest, platform, app } = args;
1004
- if (!app.splash) return;
1005
- var source = path.resolve(root, app.splash.source);
1006
- if (!FSExtra.existsSync(source)) {
1007
- throw new Error(`[vxrn] native.app.splash source does not exist: ${source}`);
1008
- }
1009
- var { data: artwork, info: metadata } = await sharp(source).rotate().trim({ background: app.splash.backgroundColor }).png().toBuffer({ resolveWithObject: true });
1010
- if (!metadata.width || !metadata.height) {
1011
- throw new Error("[vxrn] native.app.splash source must be an image");
1411
+ async function generateAdaptiveIcon(args) {
1412
+ var _app_android;
1413
+ var { root, dest, app } = args;
1414
+ var adaptiveIcon = (_app_android = app.android) === null || _app_android === void 0 ? void 0 : _app_android.adaptiveIcon;
1415
+ if (!adaptiveIcon) return;
1416
+ var res = path.join(dest, "app", "src", "main", "res");
1417
+ var layers = {
1418
+ foreground: adaptiveIcon.foreground,
1419
+ background: adaptiveIcon.background,
1420
+ monochrome: adaptiveIcon.monochrome
1421
+ };
1422
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
1423
+ try {
1424
+ for (var _iterator = Object.entries(layers)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
1425
+ var [layer, file] = _step.value;
1426
+ if (!file) continue;
1427
+ var source = path.resolve(root, file);
1428
+ if (!FSExtra.existsSync(source)) {
1429
+ throw new Error(`[vxrn] native.app.android.adaptiveIcon.${layer} does not exist: ${source}`);
1430
+ }
1431
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
1432
+ try {
1433
+ for (var _iterator1 = Object.entries(ANDROID_DENSITIES)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
1434
+ var [density, multiplier] = _step1.value;
1435
+ var pixels = 108 * multiplier;
1436
+ await sharp(source).rotate().resize(pixels, pixels, { fit: "cover" }).png().toFile(path.join(res, `mipmap-${density}`, `ic_launcher_${layer}.png`));
1437
+ }
1438
+ } catch (err) {
1439
+ _didIteratorError1 = true;
1440
+ _iteratorError1 = err;
1441
+ } finally {
1442
+ try {
1443
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1444
+ _iterator1.return();
1445
+ }
1446
+ } finally {
1447
+ if (_didIteratorError1) {
1448
+ throw _iteratorError1;
1449
+ }
1450
+ }
1451
+ }
1452
+ }
1453
+ } catch (err) {
1454
+ _didIteratorError = true;
1455
+ _iteratorError = err;
1456
+ } finally {
1457
+ try {
1458
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1459
+ _iterator.return();
1460
+ }
1461
+ } finally {
1462
+ if (_didIteratorError) {
1463
+ throw _iteratorError;
1464
+ }
1465
+ }
1012
1466
  }
1013
- var artworkWidth = (_app_splash_width = app.splash.width) !== null && _app_splash_width !== void 0 ? _app_splash_width : 200;
1014
- var artworkHeight = Number((artworkWidth * (metadata.height / metadata.width)).toFixed(3));
1015
- if (platform === "ios") {
1016
- var appDir = path.join(dest, app.name);
1017
- var splashDir = path.join(appDir, "Images.xcassets", "Splash.imageset");
1018
- FSExtra.mkdirSync(splashDir, { recursive: true });
1019
- await sharp(artwork).toFile(path.join(splashDir, "splash.png"));
1020
- FSExtra.writeFileSync(path.join(splashDir, "Contents.json"), `${JSON.stringify({
1021
- images: [{
1022
- filename: "splash.png",
1023
- idiom: "universal",
1024
- scale: "1x"
1025
- }],
1026
- info: {
1027
- author: "xcode",
1028
- version: 1
1029
- }
1030
- }, null, 2)}
1467
+ if (!adaptiveIcon.background) {
1468
+ var _adaptiveIcon_backgroundColor;
1469
+ FSExtra.writeFileSync(path.join(res, "values", "ic_launcher_background.xml"), `<?xml version="1.0" encoding="utf-8"?>
1470
+ <resources>
1471
+ <color name="ic_launcher_background">${(_adaptiveIcon_backgroundColor = adaptiveIcon.backgroundColor) !== null && _adaptiveIcon_backgroundColor !== void 0 ? _adaptiveIcon_backgroundColor : "#FFFFFF"}</color>
1472
+ </resources>
1031
1473
  `);
1032
- var red = Number.parseInt(app.splash.backgroundColor.slice(1, 3), 16) / 255;
1033
- var green = Number.parseInt(app.splash.backgroundColor.slice(3, 5), 16) / 255;
1034
- var blue = Number.parseInt(app.splash.backgroundColor.slice(5, 7), 16) / 255;
1035
- FSExtra.writeFileSync(path.join(appDir, "LaunchScreen.storyboard"), `<?xml version="1.0" encoding="UTF-8"?>
1036
- <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="launch-controller">
1037
- <device id="retina6_12" orientation="portrait" appearance="light"/>
1474
+ }
1475
+ var adaptiveXml = `<?xml version="1.0" encoding="utf-8"?>
1476
+ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
1477
+ <background android:drawable="${adaptiveIcon.background ? "@mipmap/ic_launcher_background" : "@color/ic_launcher_background"}"/>
1478
+ <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
1479
+ ${adaptiveIcon.monochrome ? " <monochrome android:drawable=\"@mipmap/ic_launcher_monochrome\"/>\n" : ""}</adaptive-icon>
1480
+ `;
1481
+ var anydpi = path.join(res, "mipmap-anydpi-v26");
1482
+ FSExtra.mkdirSync(anydpi, { recursive: true });
1483
+ for (var _i = 0, _iter = ["ic_launcher.xml", "ic_launcher_round.xml"]; _i < _iter.length; _i++) {
1484
+ var filename = _iter[_i];
1485
+ FSExtra.writeFileSync(path.join(anydpi, filename), adaptiveXml);
1486
+ }
1487
+ }
1488
+ var IOS_DARK_APPEARANCE = [{
1489
+ appearance: "luminosity",
1490
+ value: "dark"
1491
+ }];
1492
+ function srgb(hex) {
1493
+ return {
1494
+ red: Number.parseInt(hex.slice(1, 3), 16) / 255,
1495
+ green: Number.parseInt(hex.slice(3, 5), 16) / 255,
1496
+ blue: Number.parseInt(hex.slice(5, 7), 16) / 255
1497
+ };
1498
+ }
1499
+ function xcodeColorSet(light, dark) {
1500
+ var entry = function entry2(hex) {
1501
+ var { red, green, blue } = srgb(hex);
1502
+ return {
1503
+ color: {
1504
+ "color-space": "srgb",
1505
+ components: {
1506
+ red: red.toFixed(3),
1507
+ green: green.toFixed(3),
1508
+ blue: blue.toFixed(3),
1509
+ alpha: "1.000"
1510
+ }
1511
+ },
1512
+ idiom: "universal"
1513
+ };
1514
+ };
1515
+ return `${JSON.stringify({
1516
+ colors: [entry(light), ...dark ? [{
1517
+ appearances: IOS_DARK_APPEARANCE,
1518
+ ...entry(dark)
1519
+ }] : []],
1520
+ info: {
1521
+ author: "xcode",
1522
+ version: 1
1523
+ }
1524
+ }, null, 2)}
1525
+ `;
1526
+ }
1527
+ function generateAccentColor(args) {
1528
+ var _args_app_ios;
1529
+ var accent = (_args_app_ios = args.app.ios) === null || _args_app_ios === void 0 ? void 0 : _args_app_ios.accentColor;
1530
+ if (!accent) return;
1531
+ var colorDir = path.join(args.dest, args.app.name, "Images.xcassets", "AccentColor.colorset");
1532
+ FSExtra.mkdirSync(colorDir, { recursive: true });
1533
+ FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(accent.light, accent.dark));
1534
+ }
1535
+ async function generateSplashScreen(args) {
1536
+ var _app_splash_width;
1537
+ var { root, dest, platform, app } = args;
1538
+ if (!app.splash) return;
1539
+ var cover = app.splash.resizeMode === "cover";
1540
+ var prepareArtwork = async function prepareArtwork2(sourcePath, backgroundColor) {
1541
+ var _ref;
1542
+ var _app_splash;
1543
+ var source = path.resolve(root, sourcePath);
1544
+ if (!FSExtra.existsSync(source)) {
1545
+ throw new Error(`[vxrn] native.app.splash source does not exist: ${source}`);
1546
+ }
1547
+ var { width: sourceWidth, format } = await sharp(source).metadata();
1548
+ var density2 = format === "svg" && sourceWidth && !cover ? Math.min(2400, Math.ceil(72 * 4 * ((_ref = (_app_splash = app.splash) === null || _app_splash === void 0 ? void 0 : _app_splash.width) !== null && _ref !== void 0 ? _ref : 200) / sourceWidth)) : void 0;
1549
+ var image = sharp(source, density2 ? { density: density2 } : {}).rotate();
1550
+ var prepared = await (cover ? image : image.trim({ background: backgroundColor })).png().toBuffer({ resolveWithObject: true });
1551
+ if (!prepared.info.width || !prepared.info.height) {
1552
+ throw new Error("[vxrn] native.app.splash source must be an image");
1553
+ }
1554
+ return prepared;
1555
+ };
1556
+ var { data: artwork, info: metadata } = await prepareArtwork(app.splash.source, app.splash.backgroundColor);
1557
+ var dark = app.splash.dark;
1558
+ var darkArtwork = (dark === null || dark === void 0 ? void 0 : dark.source) ? (await prepareArtwork(dark.source, dark.backgroundColor)).data : void 0;
1559
+ var artworkWidth = (_app_splash_width = app.splash.width) !== null && _app_splash_width !== void 0 ? _app_splash_width : 200;
1560
+ var artworkHeight = Number((artworkWidth * (metadata.height / metadata.width)).toFixed(3));
1561
+ var readBackground = function readBackground2(sourcePath) {
1562
+ var source = path.resolve(root, sourcePath);
1563
+ if (!FSExtra.existsSync(source)) {
1564
+ throw new Error(`[vxrn] native.app.splash backgroundImage does not exist: ${source}`);
1565
+ }
1566
+ return sharp(source).rotate().png().toBuffer({ resolveWithObject: true });
1567
+ };
1568
+ if (platform === "ios") {
1569
+ var appDir = path.join(dest, app.name);
1570
+ var assets = path.join(appDir, "Images.xcassets");
1571
+ var writeImageSet = async function writeImageSet2(name, light, dark2, pointWidth) {
1572
+ var dir = path.join(assets, `${name}.imageset`);
1573
+ FSExtra.mkdirSync(dir, { recursive: true });
1574
+ var scales = pointWidth === void 0 ? [1] : [
1575
+ 1,
1576
+ 2,
1577
+ 3
1578
+ ];
1579
+ var images = [];
1580
+ for (var _i = 0, _iter = [[
1581
+ light,
1582
+ "",
1583
+ void 0
1584
+ ], [
1585
+ dark2,
1586
+ "-dark",
1587
+ IOS_DARK_APPEARANCE
1588
+ ]]; _i < _iter.length; _i++) {
1589
+ var [variant, suffix, appearances] = _iter[_i];
1590
+ if (!variant) continue;
1591
+ var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1592
+ try {
1593
+ for (var _iterator2 = scales[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
1594
+ var scale = _step2.value;
1595
+ var filename = `${name.toLowerCase()}${suffix}${scale === 1 ? "" : `@${scale}x`}.png`;
1596
+ var output = sharp(variant);
1597
+ await (pointWidth === void 0 ? output : output.resize({ width: Math.round(pointWidth * scale) })).png().toFile(path.join(dir, filename));
1598
+ images.push({
1599
+ ...appearances ? { appearances } : {},
1600
+ filename,
1601
+ idiom: "universal",
1602
+ scale: `${scale}x`
1603
+ });
1604
+ }
1605
+ } catch (err) {
1606
+ _didIteratorError2 = true;
1607
+ _iteratorError2 = err;
1608
+ } finally {
1609
+ try {
1610
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
1611
+ _iterator2.return();
1612
+ }
1613
+ } finally {
1614
+ if (_didIteratorError2) {
1615
+ throw _iteratorError2;
1616
+ }
1617
+ }
1618
+ }
1619
+ }
1620
+ FSExtra.writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1621
+ images,
1622
+ info: {
1623
+ author: "xcode",
1624
+ version: 1
1625
+ }
1626
+ }, null, 2)}
1627
+ `);
1628
+ };
1629
+ await writeImageSet("Splash", artwork, darkArtwork, cover ? void 0 : artworkWidth);
1630
+ var background = app.splash.backgroundImage ? await readBackground(app.splash.backgroundImage) : void 0;
1631
+ var darkBackground = (dark === null || dark === void 0 ? void 0 : dark.backgroundImage) ? (await readBackground(dark.backgroundImage)).data : void 0;
1632
+ if (background) {
1633
+ await writeImageSet("SplashBackgroundImage", background.data, darkBackground, void 0);
1634
+ }
1635
+ var colorDir = path.join(assets, "SplashBackground.colorset");
1636
+ FSExtra.mkdirSync(colorDir, { recursive: true });
1637
+ FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(app.splash.backgroundColor, dark === null || dark === void 0 ? void 0 : dark.backgroundColor));
1638
+ var { red, green, blue } = srgb(app.splash.backgroundColor);
1639
+ FSExtra.writeFileSync(path.join(appDir, "LaunchScreen.storyboard"), `<?xml version="1.0" encoding="UTF-8"?>
1640
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="launch-controller">
1641
+ <device id="retina6_12" orientation="portrait" appearance="light"/>
1038
1642
  <dependencies>
1039
1643
  <deployment identifier="iOS"/>
1040
1644
  <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
@@ -1046,15 +1650,23 @@ async function generateSplashScreen(args) {
1046
1650
  <viewController id="launch-controller" sceneMemberID="viewController">
1047
1651
  <view key="view" contentMode="scaleToFill" id="launch-view">
1048
1652
  <rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
1049
- <subviews>
1050
- <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" image="Splash" translatesAutoresizingMaskIntoConstraints="NO" id="splash-image"/>
1653
+ <subviews>${background ? `
1654
+ <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="SplashBackgroundImage" translatesAutoresizingMaskIntoConstraints="NO" id="splash-background"/>` : ""}
1655
+ <imageView userInteractionEnabled="NO" contentMode="${cover ? "scaleAspectFill" : "scaleAspectFit"}" image="Splash" translatesAutoresizingMaskIntoConstraints="NO" id="splash-image"/>
1051
1656
  </subviews>
1052
- <color key="backgroundColor" red="${red}" green="${green}" blue="${blue}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
1053
- <constraints>
1054
- <constraint firstItem="splash-image" firstAttribute="centerX" secondItem="launch-view" secondAttribute="centerX" id="splash-center-x"/>
1657
+ <color key="backgroundColor" name="SplashBackground"/>
1658
+ <constraints>${background ? `
1659
+ <constraint firstItem="splash-background" firstAttribute="leading" secondItem="launch-view" secondAttribute="leading" id="splash-background-leading"/>
1660
+ <constraint firstItem="splash-background" firstAttribute="trailing" secondItem="launch-view" secondAttribute="trailing" id="splash-background-trailing"/>
1661
+ <constraint firstItem="splash-background" firstAttribute="top" secondItem="launch-view" secondAttribute="top" id="splash-background-top"/>
1662
+ <constraint firstItem="splash-background" firstAttribute="bottom" secondItem="launch-view" secondAttribute="bottom" id="splash-background-bottom"/>` : ""}
1663
+ ${cover ? ` <constraint firstItem="splash-image" firstAttribute="leading" secondItem="launch-view" secondAttribute="leading" id="splash-leading"/>
1664
+ <constraint firstItem="splash-image" firstAttribute="trailing" secondItem="launch-view" secondAttribute="trailing" id="splash-trailing"/>
1665
+ <constraint firstItem="splash-image" firstAttribute="top" secondItem="launch-view" secondAttribute="top" id="splash-top"/>
1666
+ <constraint firstItem="splash-image" firstAttribute="bottom" secondItem="launch-view" secondAttribute="bottom" id="splash-bottom"/>` : ` <constraint firstItem="splash-image" firstAttribute="centerX" secondItem="launch-view" secondAttribute="centerX" id="splash-center-x"/>
1055
1667
  <constraint firstItem="splash-image" firstAttribute="centerY" secondItem="launch-view" secondAttribute="centerY" id="splash-center-y"/>
1056
1668
  <constraint firstItem="splash-image" firstAttribute="width" constant="${artworkWidth}" id="splash-width"/>
1057
- <constraint firstItem="splash-image" firstAttribute="height" constant="${artworkHeight}" id="splash-height"/>
1669
+ <constraint firstItem="splash-image" firstAttribute="height" constant="${artworkHeight}" id="splash-height"/>`}
1058
1670
  </constraints>
1059
1671
  </view>
1060
1672
  </viewController>
@@ -1063,7 +1675,11 @@ async function generateSplashScreen(args) {
1063
1675
  </scene>
1064
1676
  </scenes>
1065
1677
  <resources>
1066
- <image name="Splash" width="${metadata.width}" height="${metadata.height}"/>
1678
+ <image name="Splash" width="${cover ? metadata.width : artworkWidth}" height="${cover ? metadata.height : artworkHeight}"/>${background ? `
1679
+ <image name="SplashBackgroundImage" width="${background.info.width}" height="${background.info.height}"/>` : ""}
1680
+ <namedColor name="SplashBackground">
1681
+ <color red="${red}" green="${green}" blue="${blue}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
1682
+ </namedColor>
1067
1683
  </resources>
1068
1684
  </document>
1069
1685
  `);
@@ -1071,38 +1687,59 @@ async function generateSplashScreen(args) {
1071
1687
  }
1072
1688
  var mainRes = path.join(dest, "app", "src", "main", "res");
1073
1689
  var drawable = path.join(mainRes, "drawable");
1690
+ var variants = [[artwork, "drawable"]];
1691
+ if (darkArtwork) variants.push([darkArtwork, "drawable-night"]);
1074
1692
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
1075
1693
  try {
1076
- for (var _iterator = Object.entries(ANDROID_DENSITIES)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
1077
- var [density, multiplier] = _step.value;
1078
- var canvasSize = 288 * multiplier;
1079
- var imageSize = Math.round(artworkWidth * multiplier);
1080
- var contained = await sharp(artwork).resize(imageSize, imageSize, {
1081
- fit: "contain",
1082
- background: {
1083
- r: 0,
1084
- g: 0,
1085
- b: 0,
1086
- alpha: 0
1694
+ for (var _iterator = variants[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
1695
+ var [variantArtwork, drawablePrefix] = _step.value;
1696
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
1697
+ try {
1698
+ for (var _iterator1 = Object.entries(ANDROID_DENSITIES)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
1699
+ var [density, multiplier] = _step1.value;
1700
+ var canvasSize = 288 * multiplier;
1701
+ var imageSize = Math.round(artworkWidth * multiplier);
1702
+ var contained = await sharp(variantArtwork).resize(imageSize, imageSize, {
1703
+ fit: "contain",
1704
+ background: {
1705
+ r: 0,
1706
+ g: 0,
1707
+ b: 0,
1708
+ alpha: 0
1709
+ }
1710
+ }).png().toBuffer();
1711
+ var drawableDensity = path.join(mainRes, `${drawablePrefix}-${density}`);
1712
+ FSExtra.mkdirSync(drawableDensity, { recursive: true });
1713
+ await sharp({ create: {
1714
+ width: canvasSize,
1715
+ height: canvasSize,
1716
+ channels: 4,
1717
+ background: {
1718
+ r: 0,
1719
+ g: 0,
1720
+ b: 0,
1721
+ alpha: 0
1722
+ }
1723
+ } }).composite([{
1724
+ input: contained,
1725
+ left: Math.round((canvasSize - imageSize) / 2),
1726
+ top: Math.round((canvasSize - imageSize) / 2)
1727
+ }]).png().toFile(path.join(drawableDensity, "splash.png"));
1087
1728
  }
1088
- }).png().toBuffer();
1089
- var drawableDensity = path.join(mainRes, `drawable-${density}`);
1090
- FSExtra.mkdirSync(drawableDensity, { recursive: true });
1091
- await sharp({ create: {
1092
- width: canvasSize,
1093
- height: canvasSize,
1094
- channels: 4,
1095
- background: {
1096
- r: 0,
1097
- g: 0,
1098
- b: 0,
1099
- alpha: 0
1729
+ } catch (err) {
1730
+ _didIteratorError1 = true;
1731
+ _iteratorError1 = err;
1732
+ } finally {
1733
+ try {
1734
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1735
+ _iterator1.return();
1736
+ }
1737
+ } finally {
1738
+ if (_didIteratorError1) {
1739
+ throw _iteratorError1;
1740
+ }
1100
1741
  }
1101
- } }).composite([{
1102
- input: contained,
1103
- left: Math.round((canvasSize - imageSize) / 2),
1104
- top: Math.round((canvasSize - imageSize) / 2)
1105
- }]).png().toFile(path.join(drawableDensity, "splash.png"));
1742
+ }
1106
1743
  }
1107
1744
  } catch (err) {
1108
1745
  _didIteratorError = true;
@@ -1118,10 +1755,25 @@ async function generateSplashScreen(args) {
1118
1755
  }
1119
1756
  }
1120
1757
  }
1758
+ var background1 = app.splash.backgroundImage ? await readBackground(app.splash.backgroundImage) : void 0;
1759
+ var darkBackground1 = (dark === null || dark === void 0 ? void 0 : dark.backgroundImage) ? (await readBackground(dark.backgroundImage)).data : void 0;
1760
+ if (background1) {
1761
+ var nodpi = path.join(mainRes, "drawable-nodpi");
1762
+ FSExtra.mkdirSync(nodpi, { recursive: true });
1763
+ FSExtra.writeFileSync(path.join(nodpi, "splash_background.png"), background1.data);
1764
+ if (darkBackground1) {
1765
+ var nightNodpi = path.join(mainRes, "drawable-night-nodpi");
1766
+ FSExtra.mkdirSync(nightNodpi, { recursive: true });
1767
+ FSExtra.writeFileSync(path.join(nightNodpi, "splash_background.png"), darkBackground1);
1768
+ }
1769
+ }
1121
1770
  FSExtra.writeFileSync(path.join(drawable, "launch_screen.xml"), `<?xml version="1.0" encoding="utf-8"?>
1122
1771
  <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
1123
1772
  <item android:drawable="@color/splash_background" />
1124
- <item>
1773
+ ${background1 ? ` <item>
1774
+ <bitmap android:gravity="fill" android:src="@drawable/splash_background" />
1775
+ </item>
1776
+ ` : ""} <item>
1125
1777
  <bitmap android:gravity="center" android:src="@drawable/splash" />
1126
1778
  </item>
1127
1779
  </layer-list>
@@ -1131,6 +1783,14 @@ async function generateSplashScreen(args) {
1131
1783
  <color name="splash_background">${app.splash.backgroundColor}</color>
1132
1784
  </resources>
1133
1785
  `);
1786
+ if (dark) {
1787
+ FSExtra.mkdirSync(path.join(mainRes, "values-night"), { recursive: true });
1788
+ FSExtra.writeFileSync(path.join(mainRes, "values-night", "colors.xml"), `<?xml version="1.0" encoding="utf-8"?>
1789
+ <resources>
1790
+ <color name="splash_background">${dark.backgroundColor}</color>
1791
+ </resources>
1792
+ `);
1793
+ }
1134
1794
  var stylesPath = path.join(mainRes, "values", "styles.xml");
1135
1795
  var styles = FSExtra.readFileSync(stylesPath, "utf8").replace(" <!-- Customize your theme here. -->", " <item name=\"android:windowBackground\">@drawable/launch_screen</item>");
1136
1796
  FSExtra.writeFileSync(stylesPath, styles);
@@ -1155,7 +1815,7 @@ function renderPrebuildFile(args) {
1155
1815
  destRelativePath = destRelativePath.replace(/HelloWorld/g, appName).replace(/helloworld/g, appName.toLowerCase());
1156
1816
  var rendered = content;
1157
1817
  if (rendered !== null) {
1158
- var _app_imagePicker, _app_notifications, _app_android, _app_notifications1, _app_android1, _app_ios, _app_android2;
1818
+ var _app_imagePicker, _app_notifications, _app_ios, _app_android, _app_notifications1, _app_android1, _app_android_permissions, _app_android2, _app_android_blockedPermissions, _app_android3, _app_android_appLinks, _app_android4, _app_ios1, _app_ios2, _app_android5, _app_android6, _app_android7;
1159
1819
  var replacements = [];
1160
1820
  if (platform === "ios" && app.ios) {
1161
1821
  replacements.push([IOS_BUNDLE_PLACEHOLDER, app.ios.bundleId]);
@@ -1185,7 +1845,8 @@ function renderPrebuildFile(args) {
1185
1845
  }
1186
1846
  }
1187
1847
  if (platform === "ios" && relativePath.endsWith("/Info.plist")) {
1188
- var _app_ios1, _app_ios2, _app_notifications2, _app_ios3;
1848
+ var _ref, _ref1, _ref2;
1849
+ var _app_ios3, _app_ios4, _app_ios5, _app_photoLibrary, _app_notifications2, _app_ios6, _app_ios_backgroundTasks, _app_ios7, _app_ios_backgroundTasks1, _app_ios8, _app_ios9, _app_audio, _app_location, _app_fonts, _app_ios10;
1189
1850
  var stamps = [];
1190
1851
  if (schemes.length) {
1191
1852
  stamps.push(` <key>CFBundleURLTypes</key>
@@ -1202,29 +1863,128 @@ ${schemes.map(function(scheme) {
1202
1863
  </dict>
1203
1864
  </array>`);
1204
1865
  }
1205
- if (((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.usesNonExemptEncryption) !== void 0) {
1866
+ if (((_app_ios3 = app.ios) === null || _app_ios3 === void 0 ? void 0 : _app_ios3.usesNonExemptEncryption) !== void 0) {
1206
1867
  stamps.push(` <key>ITSAppUsesNonExemptEncryption</key>
1207
1868
  <${app.ios.usesNonExemptEncryption ? "true" : "false"}/>`);
1208
1869
  }
1209
- if ((_app_ios2 = app.ios) === null || _app_ios2 === void 0 ? void 0 : _app_ios2.fileSharing) {
1870
+ if ((_app_ios4 = app.ios) === null || _app_ios4 === void 0 ? void 0 : _app_ios4.accentColor) {
1871
+ stamps.push(" <key>NSAccentColorName</key>\n <string>AccentColor</string>");
1872
+ }
1873
+ if ((_app_ios5 = app.ios) === null || _app_ios5 === void 0 ? void 0 : _app_ios5.fileSharing) {
1210
1874
  stamps.push(` <key>UIFileSharingEnabled</key>
1211
1875
  <true/>
1212
1876
  <key>LSSupportsOpeningDocumentsInPlace</key>
1213
1877
  <true/>`);
1214
1878
  }
1879
+ if (((_app_photoLibrary = app.photoLibrary) === null || _app_photoLibrary === void 0 ? void 0 : _app_photoLibrary.readWrite) !== void 0) {
1880
+ stamps.push(" <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>\n <true/>");
1881
+ }
1215
1882
  if (app.notifications !== void 0) {
1216
- stamps.push(` <key>OneNativeNotificationsEnabled</key>
1883
+ stamps.push(` <key>${notificationsHost.enabledInfoPlistKey}</key>
1217
1884
  <true/>`);
1218
1885
  }
1219
1886
  if (((_app_notifications2 = app.notifications) === null || _app_notifications2 === void 0 ? void 0 : _app_notifications2.push) === true) {
1220
- stamps.push(` <key>OneNativeNotificationsPush</key>
1887
+ stamps.push(` <key>${notificationsHost.pushInfoPlistKey}</key>
1221
1888
  <true/>`);
1222
1889
  }
1223
- if ((_app_ios3 = app.ios) === null || _app_ios3 === void 0 ? void 0 : _app_ios3.widgets) {
1890
+ if ((_app_ios6 = app.ios) === null || _app_ios6 === void 0 ? void 0 : _app_ios6.widgets) {
1224
1891
  stamps.push(" <key>NSSupportsLiveActivities</key>\n <true/>");
1225
1892
  }
1226
- if (app.pictureInPicture) {
1227
- stamps.push(" <key>UIBackgroundModes</key>\n <array>\n <string>audio</string>\n </array>");
1893
+ var refreshTasks = (_ref = (_app_ios7 = app.ios) === null || _app_ios7 === void 0 ? void 0 : (_app_ios_backgroundTasks = _app_ios7.backgroundTasks) === null || _app_ios_backgroundTasks === void 0 ? void 0 : _app_ios_backgroundTasks.refresh) !== null && _ref !== void 0 ? _ref : [];
1894
+ var processingTasks = (_ref1 = (_app_ios8 = app.ios) === null || _app_ios8 === void 0 ? void 0 : (_app_ios_backgroundTasks1 = _app_ios8.backgroundTasks) === null || _app_ios_backgroundTasks1 === void 0 ? void 0 : _app_ios_backgroundTasks1.processing) !== null && _ref1 !== void 0 ? _ref1 : [];
1895
+ if (refreshTasks.length || processingTasks.length) {
1896
+ var plistArray = function plistArray2(key, identifiers) {
1897
+ return ` <key>${key}</key>
1898
+ <array>
1899
+ ${identifiers.map(function(identifier) {
1900
+ return ` <string>${escapeXml(identifier)}</string>`;
1901
+ }).join("\n")}
1902
+ </array>`;
1903
+ };
1904
+ stamps.push(plistArray("BGTaskSchedulerPermittedIdentifiers", [...refreshTasks, ...processingTasks]));
1905
+ stamps.push(plistArray("OneBackgroundRefreshTaskIdentifiers", refreshTasks));
1906
+ stamps.push(plistArray("OneBackgroundProcessingTaskIdentifiers", processingTasks));
1907
+ }
1908
+ if ((_app_ios9 = app.ios) === null || _app_ios9 === void 0 ? void 0 : _app_ios9.appIntents) {
1909
+ stamps.push(` <key>OneAppIntentIdentifiers</key>
1910
+ <array>
1911
+ ${app.ios.appIntents.actions.map(function(action) {
1912
+ return ` <string>${escapeXml(action.id)}</string>`;
1913
+ }).join("\n")}
1914
+ </array>`);
1915
+ }
1916
+ var backgroundModes = [
1917
+ ...app.pictureInPicture || ((_app_audio = app.audio) === null || _app_audio === void 0 ? void 0 : _app_audio.background) ? ["audio"] : [],
1918
+ ...((_app_location = app.location) === null || _app_location === void 0 ? void 0 : _app_location.background) ? ["location"] : [],
1919
+ ...refreshTasks.length ? ["fetch"] : [],
1920
+ ...processingTasks.length ? ["processing"] : []
1921
+ ];
1922
+ if (backgroundModes.length) {
1923
+ stamps.push(` <key>UIBackgroundModes</key>
1924
+ <array>
1925
+ ${backgroundModes.map(function(mode) {
1926
+ return ` <string>${mode}</string>`;
1927
+ }).join("\n")}
1928
+ </array>`);
1929
+ }
1930
+ if (app.updates !== void 0) {
1931
+ if (app.updates.url !== void 0) {
1932
+ stamps.push(` <key>${updatesHost.urlInfoPlistKey}</key>
1933
+ <string>${escapeXml(app.updates.url)}</string>`);
1934
+ }
1935
+ stamps.push(` <key>${updatesHost.runtimeVersionInfoPlistKey}</key>
1936
+ <string>${escapeXml(app.updates.runtimeVersion)}</string>`);
1937
+ }
1938
+ if ((_app_fonts = app.fonts) === null || _app_fonts === void 0 ? void 0 : _app_fonts.length) {
1939
+ stamps.push(` <key>UIAppFonts</key>
1940
+ <array>
1941
+ ${app.fonts.map(function(font) {
1942
+ return ` <string>${escapeXml(fontFileName(font))}</string>`;
1943
+ }).join("\n")}
1944
+ </array>`);
1945
+ }
1946
+ if (app.userInterfaceStyle !== void 0) {
1947
+ stamps.push(` <key>UIUserInterfaceStyle</key>
1948
+ <string>${app.userInterfaceStyle === "light" ? "Light" : app.userInterfaceStyle === "dark" ? "Dark" : "Automatic"}</string>`);
1949
+ }
1950
+ if (app.orientation !== void 0) {
1951
+ var phoneOrientations = app.orientation === "portrait" ? PORTRAIT_ORIENTATIONS : app.orientation === "landscape" ? LANDSCAPE_ORIENTATIONS : [...PORTRAIT_ORIENTATIONS, ...LANDSCAPE_ORIENTATIONS];
1952
+ var phoneList = /\t<key>UISupportedInterfaceOrientations<\/key>\n\t<array>\n[\s\S]*?\t<\/array>/;
1953
+ if (!phoneList.test(rendered)) {
1954
+ throw new Error(`[vxrn] prebuild template ${relativePath} lost its UISupportedInterfaceOrientations list`);
1955
+ }
1956
+ rendered = rendered.replace(phoneList, ` <key>UISupportedInterfaceOrientations</key>
1957
+ <array>
1958
+ ${phoneOrientations.map(function(orientation) {
1959
+ return ` <string>${orientation}</string>`;
1960
+ }).join("\n")}
1961
+ </array>`);
1962
+ }
1963
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
1964
+ try {
1965
+ var _loop = function() {
1966
+ var [key, value2] = _step1.value;
1967
+ if (rendered.includes(`<key>${key}</key>`) || stamps.some(function(stamp) {
1968
+ return stamp.includes(`<key>${key}</key>`);
1969
+ })) {
1970
+ throw new Error(`[vxrn] native.app.ios.infoPlist sets ${key}, which the template or native.app already writes: use its field`);
1971
+ }
1972
+ stamps.push(renderPlistEntries({ [key]: value2 }, " "));
1973
+ };
1974
+ for (var _iterator1 = Object.entries((_ref2 = (_app_ios10 = app.ios) === null || _app_ios10 === void 0 ? void 0 : _app_ios10.infoPlist) !== null && _ref2 !== void 0 ? _ref2 : {})[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) _loop();
1975
+ } catch (err) {
1976
+ _didIteratorError1 = true;
1977
+ _iteratorError1 = err;
1978
+ } finally {
1979
+ try {
1980
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1981
+ _iterator1.return();
1982
+ }
1983
+ } finally {
1984
+ if (_didIteratorError1) {
1985
+ throw _iteratorError1;
1986
+ }
1987
+ }
1228
1988
  }
1229
1989
  if (stamps.length) {
1230
1990
  var anchor = " <key>LSRequiresIPhoneOS</key>";
@@ -1233,50 +1993,178 @@ ${schemes.map(function(scheme) {
1233
1993
  ${anchor}`);
1234
1994
  }
1235
1995
  }
1236
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && ((_app_imagePicker = app.imagePicker) === null || _app_imagePicker === void 0 ? void 0 : _app_imagePicker.camera) !== void 0) {
1996
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && (((_app_imagePicker = app.imagePicker) === null || _app_imagePicker === void 0 ? void 0 : _app_imagePicker.camera) !== void 0 || app.speech !== void 0)) {
1997
+ var _app_imagePicker1;
1237
1998
  var anchor1 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1238
1999
  if (!rendered.includes(anchor1)) {
1239
- throw new Error("[vxrn] cannot stamp the camera permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2000
+ throw new Error("[vxrn] cannot stamp the camera or microphone permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2001
+ }
2002
+ var stamps1 = [];
2003
+ if (((_app_imagePicker1 = app.imagePicker) === null || _app_imagePicker1 === void 0 ? void 0 : _app_imagePicker1.camera) !== void 0) {
2004
+ stamps1.push(" <uses-permission android:name=\"android.permission.CAMERA\" />");
2005
+ }
2006
+ if (app.speech !== void 0) {
2007
+ stamps1.push(" <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />", " <queries>\n <intent>\n <action android:name=\"android.speech.RecognitionService\" />\n </intent>\n </queries>");
1240
2008
  }
1241
2009
  rendered = rendered.replace(anchor1, `${anchor1}
1242
- <uses-permission android:name="android.permission.CAMERA" />`);
2010
+ ${stamps1.join("\n")}`);
1243
2011
  }
1244
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.notifications !== void 0) {
2012
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.location !== void 0) {
1245
2013
  var anchor2 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1246
2014
  if (!rendered.includes(anchor2)) {
1247
- throw new Error("[vxrn] cannot stamp notification permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2015
+ throw new Error("[vxrn] cannot stamp location permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2016
+ }
2017
+ var stamps2 = [" <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />", " <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />"];
2018
+ if (app.location.background) {
2019
+ stamps2.push(" <uses-permission android:name=\"android.permission.ACCESS_BACKGROUND_LOCATION\" />");
1248
2020
  }
1249
2021
  rendered = rendered.replace(anchor2, `${anchor2}
1250
- <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
1251
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />`);
1252
- if (!rendered.includes("android.permission.POST_NOTIFICATIONS")) {
2022
+ ${stamps2.join("\n")}`);
2023
+ }
2024
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.pedometer !== void 0) {
2025
+ var anchor3 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
2026
+ if (!rendered.includes(anchor3)) {
2027
+ throw new Error("[vxrn] cannot stamp the pedometer permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2028
+ }
2029
+ rendered = rendered.replace(anchor3, `${anchor3}
2030
+ <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />`);
2031
+ }
2032
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.notifications !== void 0) {
2033
+ var anchor4 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
2034
+ if (!rendered.includes(anchor4)) {
2035
+ throw new Error("[vxrn] cannot stamp notification permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2036
+ }
2037
+ rendered = rendered.replace(anchor4, [anchor4, ...notificationsHost.androidPermissions.map(function(permission) {
2038
+ return ` <uses-permission android:name="${permission}" />`;
2039
+ })].join("\n"));
2040
+ if (!rendered.includes(notificationsHost.androidPermissions[0])) {
1253
2041
  throw new Error("[vxrn] failed to stamp notification permissions into app manifest");
1254
2042
  }
1255
- rendered = rendered.replace(" </activity>\n </application>", " </activity>\n <receiver android:name=\"dev.onejs.onenative.OneNativeNotificationsReceiver\" android:exported=\"false\">\n <intent-filter>\n <action android:name=\"android.intent.action.BOOT_COMPLETED\" />\n </intent-filter>\n </receiver>\n </application>");
1256
- if (!rendered.includes("OneNativeNotificationsReceiver")) {
2043
+ rendered = rendered.replace(" </activity>\n </application>", ` </activity>
2044
+ <receiver android:name="${notificationsHost.receiver}" android:exported="false">
2045
+ <intent-filter>
2046
+ <action android:name="${notificationsHost.receiverAction}" />
2047
+ </intent-filter>
2048
+ </receiver>
2049
+ </application>`);
2050
+ if (!rendered.includes(notificationsHost.receiver)) {
1257
2051
  throw new Error("[vxrn] failed to stamp the notification receiver into app manifest");
1258
2052
  }
1259
2053
  }
1260
2054
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && ((_app_notifications = app.notifications) === null || _app_notifications === void 0 ? void 0 : _app_notifications.push) === true) {
1261
- var anchor3 = "dev.onejs.onenative.OneNativeNotificationsReceiver";
1262
- if (!rendered.includes(anchor3)) {
2055
+ var anchor5 = notificationsHost.receiver;
2056
+ if (!rendered.includes(anchor5)) {
1263
2057
  throw new Error("[vxrn] cannot stamp the push service: expected the notification receiver in app/src/main/AndroidManifest.xml");
1264
2058
  }
1265
- rendered = rendered.replace(" </receiver>\n </application>", " </receiver>\n <service android:name=\"dev.onejs.onenative.OneNativePushService\" android:exported=\"false\">\n <intent-filter>\n <action android:name=\"com.google.firebase.MESSAGING_EVENT\" />\n </intent-filter>\n </service>\n </application>");
1266
- if (!rendered.includes("OneNativePushService")) {
2059
+ rendered = rendered.replace(" </receiver>\n </application>", ` </receiver>
2060
+ <service android:name="${notificationsHost.pushService}" android:exported="false">
2061
+ <intent-filter>
2062
+ <action android:name="${notificationsHost.pushServiceAction}" />
2063
+ </intent-filter>
2064
+ </service>
2065
+ </application>`);
2066
+ if (!rendered.includes(notificationsHost.pushService)) {
1267
2067
  throw new Error("[vxrn] failed to stamp the push service into app manifest");
1268
2068
  }
1269
2069
  }
2070
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && (app.audio !== void 0 || app.photoLibrary !== void 0 || app.contacts !== void 0 || app.calendar !== void 0 || ((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.backgroundTasks) !== void 0)) {
2071
+ var _app_audio1, _app_photoLibrary1, _app_photoLibrary2, _app_calendar, _app_calendar1, _app_audio2, _app_calendar2, _app_photoLibrary3, _app_audio3, _app_ios11;
2072
+ var anchor6 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
2073
+ if (!rendered.includes(anchor6)) {
2074
+ throw new Error("[vxrn] cannot stamp media permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2075
+ }
2076
+ var stamps3 = [];
2077
+ if (((_app_audio1 = app.audio) === null || _app_audio1 === void 0 ? void 0 : _app_audio1.microphone) !== void 0 && !rendered.includes("android.permission.RECORD_AUDIO")) {
2078
+ stamps3.push(" <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />");
2079
+ }
2080
+ if (((_app_photoLibrary1 = app.photoLibrary) === null || _app_photoLibrary1 === void 0 ? void 0 : _app_photoLibrary1.readWrite) !== void 0) {
2081
+ stamps3.push(" <uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\" />", " <uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\" />", " <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" android:maxSdkVersion=\"32\" />");
2082
+ }
2083
+ if (((_app_photoLibrary2 = app.photoLibrary) === null || _app_photoLibrary2 === void 0 ? void 0 : _app_photoLibrary2.addOnly) !== void 0) {
2084
+ stamps3.push(" <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" android:maxSdkVersion=\"28\" />");
2085
+ }
2086
+ if (app.contacts !== void 0) {
2087
+ stamps3.push(" <uses-permission android:name=\"android.permission.READ_CONTACTS\" />", " <uses-permission android:name=\"android.permission.WRITE_CONTACTS\" />");
2088
+ }
2089
+ if (((_app_calendar = app.calendar) === null || _app_calendar === void 0 ? void 0 : _app_calendar.usage) !== void 0) {
2090
+ stamps3.push(" <uses-permission android:name=\"android.permission.READ_CALENDAR\" />", " <uses-permission android:name=\"android.permission.WRITE_CALENDAR\" />");
2091
+ }
2092
+ if (((_app_calendar1 = app.calendar) === null || _app_calendar1 === void 0 ? void 0 : _app_calendar1.remindersUsage) !== void 0) {
2093
+ if (!rendered.includes("android.permission.POST_NOTIFICATIONS")) {
2094
+ stamps3.push(" <uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" />");
2095
+ }
2096
+ if (!rendered.includes("android.permission.RECEIVE_BOOT_COMPLETED")) {
2097
+ stamps3.push(" <uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />");
2098
+ }
2099
+ }
2100
+ if (((_app_audio2 = app.audio) === null || _app_audio2 === void 0 ? void 0 : _app_audio2.background) === true) {
2101
+ stamps3.push(" <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />", " <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK\" />");
2102
+ }
2103
+ if (stamps3.length) {
2104
+ rendered = rendered.replace(anchor6, `${anchor6}
2105
+ ${stamps3.join("\n")}`);
2106
+ }
2107
+ var appStamps = [];
2108
+ if (((_app_calendar2 = app.calendar) === null || _app_calendar2 === void 0 ? void 0 : _app_calendar2.remindersUsage) !== void 0) {
2109
+ appStamps.push(" <meta-data android:name=\"one.calendar.reminders\" android:value=\"true\" />");
2110
+ }
2111
+ if (((_app_photoLibrary3 = app.photoLibrary) === null || _app_photoLibrary3 === void 0 ? void 0 : _app_photoLibrary3.addOnly) !== void 0) {
2112
+ appStamps.push(" <meta-data android:name=\"one.photoLibrary.addOnly\" android:value=\"true\" />");
2113
+ }
2114
+ if (((_app_audio3 = app.audio) === null || _app_audio3 === void 0 ? void 0 : _app_audio3.background) === true) {
2115
+ appStamps.push(" <meta-data android:name=\"one.audio.background\" android:value=\"true\" />", " <service android:name=\"com.margelo.nitro.one.OneAudioService\" android:exported=\"false\" android:foregroundServiceType=\"mediaPlayback\" />");
2116
+ }
2117
+ if (((_app_ios11 = app.ios) === null || _app_ios11 === void 0 ? void 0 : _app_ios11.backgroundTasks) !== void 0) {
2118
+ var _app_ios_backgroundTasks_refresh, _app_ios_backgroundTasks_processing;
2119
+ var refreshTasks1 = (_app_ios_backgroundTasks_refresh = app.ios.backgroundTasks.refresh) !== null && _app_ios_backgroundTasks_refresh !== void 0 ? _app_ios_backgroundTasks_refresh : [];
2120
+ var processingTasks1 = (_app_ios_backgroundTasks_processing = app.ios.backgroundTasks.processing) !== null && _app_ios_backgroundTasks_processing !== void 0 ? _app_ios_backgroundTasks_processing : [];
2121
+ if (refreshTasks1.length) {
2122
+ appStamps.push(` <meta-data android:name="one.backgroundTasks.refresh" android:value="${escapeXml(refreshTasks1.join(","))}" />`);
2123
+ }
2124
+ if (processingTasks1.length) {
2125
+ appStamps.push(` <meta-data android:name="one.backgroundTasks.processing" android:value="${escapeXml(processingTasks1.join(","))}" />`);
2126
+ }
2127
+ }
2128
+ if (appStamps.length) {
2129
+ var appAnchor = " </application>";
2130
+ if (!rendered.includes(appAnchor)) {
2131
+ throw new Error("[vxrn] cannot stamp media components: expected </application> in app/src/main/AndroidManifest.xml");
2132
+ }
2133
+ rendered = rendered.replace(appAnchor, `${appStamps.join("\n")}
2134
+ ${appAnchor}`);
2135
+ }
2136
+ }
2137
+ if (platform === "android" && relativePath === "app/src/main/java/com/helloworld/MainApplication.kt" && app.updates !== void 0) {
2138
+ rendered = patchAndroidMainApplicationUpdatesHost(rendered);
2139
+ }
2140
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.updates !== void 0) {
2141
+ var anchor7 = " </application>";
2142
+ if (!rendered.includes(anchor7)) {
2143
+ throw new Error("[vxrn] cannot stamp the updates config: expected </application> in app/src/main/AndroidManifest.xml");
2144
+ }
2145
+ var stamps4 = [];
2146
+ if (app.updates.url !== void 0) {
2147
+ stamps4.push(` <meta-data android:name="dev.onejs.updates.url" android:value="${escapeXml(app.updates.url)}" />`);
2148
+ }
2149
+ stamps4.push(" <meta-data android:name=\"dev.onejs.updates.runtimeVersion\" android:value=\"@string/one_updates_runtime_version\" />");
2150
+ rendered = rendered.replace(anchor7, `${stamps4.join("\n")}
2151
+ ${anchor7}`);
2152
+ }
2153
+ if (platform === "android" && relativePath === "app/src/main/res/values/strings.xml" && app.updates !== void 0) {
2154
+ var version = app.updates.runtimeVersion.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
2155
+ rendered = rendered.replace("</resources>", ` <string name="one_updates_runtime_version" translatable="false">"${escapeXml(version)}"</string>
2156
+ </resources>`);
2157
+ }
1270
2158
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && ((_app_android = app.android) === null || _app_android === void 0 ? void 0 : _app_android.googleMapsApiKey) !== void 0) {
1271
- var anchor4 = " </application>";
1272
- if (!rendered.includes(anchor4)) {
2159
+ var anchor8 = " </application>";
2160
+ if (!rendered.includes(anchor8)) {
1273
2161
  throw new Error("[vxrn] cannot stamp the maps api key: expected </application> in app/src/main/AndroidManifest.xml");
1274
2162
  }
1275
- rendered = rendered.replace(anchor4, ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(app.android.googleMapsApiKey)}" />
1276
- ${anchor4}`);
2163
+ rendered = rendered.replace(anchor8, ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(app.android.googleMapsApiKey)}" />
2164
+ ${anchor8}`);
1277
2165
  }
1278
2166
  if (platform === "android" && relativePath === "gradle.properties" && ((_app_notifications1 = app.notifications) === null || _app_notifications1 === void 0 ? void 0 : _app_notifications1.push) === true) {
1279
- var line = "oneNativePush=true";
2167
+ var line = `${notificationsHost.pushGradleProperty}=true`;
1280
2168
  if (!rendered.includes(line)) {
1281
2169
  var trailed = rendered.endsWith("\n") ? rendered : `${rendered}
1282
2170
  `;
@@ -1297,12 +2185,60 @@ ${line1}
1297
2185
  `;
1298
2186
  }
1299
2187
  }
2188
+ if (platform === "android" && relativePath === "app/src/main/res/values/styles.xml" && (app.userInterfaceStyle === "light" || app.userInterfaceStyle === "dark")) {
2189
+ var dayNight = "parent=\"Theme.AppCompat.DayNight.NoActionBar\"";
2190
+ if (!rendered.includes(dayNight)) {
2191
+ throw new Error(`[vxrn] cannot lock userInterfaceStyle: expected ${dayNight} in app/src/main/res/values/styles.xml`);
2192
+ }
2193
+ rendered = rendered.replace(dayNight, app.userInterfaceStyle === "light" ? "parent=\"Theme.AppCompat.Light.NoActionBar\"" : "parent=\"Theme.AppCompat.NoActionBar\"");
2194
+ }
2195
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && (((_app_android2 = app.android) === null || _app_android2 === void 0 ? void 0 : (_app_android_permissions = _app_android2.permissions) === null || _app_android_permissions === void 0 ? void 0 : _app_android_permissions.length) || ((_app_android3 = app.android) === null || _app_android3 === void 0 ? void 0 : (_app_android_blockedPermissions = _app_android3.blockedPermissions) === null || _app_android_blockedPermissions === void 0 ? void 0 : _app_android_blockedPermissions.length))) {
2196
+ var _ref3, _ref4;
2197
+ var _app_android8, _app_android9, _app_android_blockedPermissions1, _app_android10;
2198
+ var anchor9 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
2199
+ if (!rendered.includes(anchor9)) {
2200
+ throw new Error("[vxrn] cannot stamp permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
2201
+ }
2202
+ var permissionName = function permissionName2(name) {
2203
+ return name.includes(".") ? name : `android.permission.${name}`;
2204
+ };
2205
+ var lines = [...((_ref3 = (_app_android8 = app.android) === null || _app_android8 === void 0 ? void 0 : _app_android8.permissions) !== null && _ref3 !== void 0 ? _ref3 : []).map(function(name) {
2206
+ return ` <uses-permission android:name="${permissionName(name)}" />`;
2207
+ }), ...((_ref4 = (_app_android9 = app.android) === null || _app_android9 === void 0 ? void 0 : _app_android9.blockedPermissions) !== null && _ref4 !== void 0 ? _ref4 : []).map(function(name) {
2208
+ return ` <uses-permission android:name="${permissionName(name)}" tools:node="remove" />`;
2209
+ })];
2210
+ rendered = rendered.replace(anchor9, `${anchor9}
2211
+ ${lines.join("\n")}`);
2212
+ if (((_app_android10 = app.android) === null || _app_android10 === void 0 ? void 0 : (_app_android_blockedPermissions1 = _app_android10.blockedPermissions) === null || _app_android_blockedPermissions1 === void 0 ? void 0 : _app_android_blockedPermissions1.length) && !rendered.includes("xmlns:tools=")) {
2213
+ rendered = rendered.replace("xmlns:android=\"http://schemas.android.com/apk/res/android\"", "xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/tools\"");
2214
+ }
2215
+ }
2216
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && ((_app_android4 = app.android) === null || _app_android4 === void 0 ? void 0 : (_app_android_appLinks = _app_android4.appLinks) === null || _app_android_appLinks === void 0 ? void 0 : _app_android_appLinks.length)) {
2217
+ rendered = rendered.replace(" </activity>", ` <intent-filter android:autoVerify="true">
2218
+ <action android:name="android.intent.action.VIEW" />
2219
+ <category android:name="android.intent.category.DEFAULT" />
2220
+ <category android:name="android.intent.category.BROWSABLE" />
2221
+ <data android:scheme="https" />
2222
+ ${app.android.appLinks.map(function(link) {
2223
+ return ` <data android:host="${link.host}"${link.pathPrefix ? ` android:pathPrefix="${link.pathPrefix}"` : ""} />`;
2224
+ }).join("\n")}
2225
+ </intent-filter>
2226
+ </activity>`);
2227
+ }
2228
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.orientation !== void 0) {
2229
+ var anchor10 = "android:name=\".MainActivity\"";
2230
+ if (!rendered.includes(anchor10)) {
2231
+ throw new Error("[vxrn] cannot stamp the orientation: expected .MainActivity in app/src/main/AndroidManifest.xml");
2232
+ }
2233
+ rendered = rendered.replace(anchor10, `${anchor10}
2234
+ android:screenOrientation="${app.orientation === "default" ? "unspecified" : app.orientation}"`);
2235
+ }
1300
2236
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.pictureInPicture) {
1301
- var anchor5 = "android:name=\".MainActivity\"";
1302
- if (!rendered.includes(anchor5)) {
2237
+ var anchor11 = "android:name=\".MainActivity\"";
2238
+ if (!rendered.includes(anchor11)) {
1303
2239
  throw new Error("[vxrn] cannot stamp picture in picture: expected .MainActivity in app/src/main/AndroidManifest.xml");
1304
2240
  }
1305
- rendered = rendered.replace(anchor5, `${anchor5}
2241
+ rendered = rendered.replace(anchor11, `${anchor11}
1306
2242
  android:supportsPictureInPicture="true"`);
1307
2243
  }
1308
2244
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && schemes.length) {
@@ -1317,35 +2253,136 @@ ${schemes.map(function(scheme) {
1317
2253
  </activity>`);
1318
2254
  }
1319
2255
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1320
- var _app_ios4;
1321
- rendered = rendered.replace(/TARGETED_DEVICE_FAMILY = "1,2";/g, `TARGETED_DEVICE_FAMILY = "${((_app_ios4 = app.ios) === null || _app_ios4 === void 0 ? void 0 : _app_ios4.tablet) ? "1,2" : "1"}";`);
2256
+ var _app_ios12;
2257
+ rendered = rendered.replace(/TARGETED_DEVICE_FAMILY = "1,2";/g, `TARGETED_DEVICE_FAMILY = "${((_app_ios12 = app.ios) === null || _app_ios12 === void 0 ? void 0 : _app_ios12.tablet) ? "1,2" : "1"}";`);
1322
2258
  }
1323
2259
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1324
- var _app_ios5;
2260
+ var _app_ios13;
1325
2261
  if (app.version !== void 0) {
1326
2262
  rendered = rendered.replace(/MARKETING_VERSION = [^;]+;/g, `MARKETING_VERSION = "${app.version}";`);
1327
2263
  }
1328
- if (((_app_ios5 = app.ios) === null || _app_ios5 === void 0 ? void 0 : _app_ios5.buildNumber) !== void 0) {
2264
+ if (((_app_ios13 = app.ios) === null || _app_ios13 === void 0 ? void 0 : _app_ios13.buildNumber) !== void 0) {
1329
2265
  rendered = rendered.replace(/CURRENT_PROJECT_VERSION = [^;]+;/g, `CURRENT_PROJECT_VERSION = ${app.ios.buildNumber};`);
1330
2266
  }
1331
2267
  }
2268
+ if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj") && ((_app_ios1 = app.ios) === null || _app_ios1 === void 0 ? void 0 : _app_ios1.alternateIcons) !== void 0) {
2269
+ var anchor12 = "ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;";
2270
+ if (!rendered.includes(anchor12)) {
2271
+ throw new Error("[vxrn] prebuild template lost its primary app icon build setting");
2272
+ }
2273
+ var names = Object.keys(app.ios.alternateIcons).sort().join(" ");
2274
+ rendered = rendered.replaceAll(anchor12, `${anchor12}
2275
+ ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "${names}";`);
2276
+ }
1332
2277
  if (platform === "ios" && relativePath.endsWith("/Info.plist")) {
1333
- var _app_imagePicker1;
1334
- if (((_app_imagePicker1 = app.imagePicker) === null || _app_imagePicker1 === void 0 ? void 0 : _app_imagePicker1.camera) !== void 0) {
1335
- var anchor6 = " <key>LSRequiresIPhoneOS</key>";
1336
- if (!rendered.includes(anchor6)) {
1337
- throw new Error("[vxrn] cannot stamp NSCameraUsageDescription: expected LSRequiresIPhoneOS in Info.plist");
2278
+ var _app_imagePicker2, _app_imagePicker3, _app_ios14, _app_audio4;
2279
+ var usage = /* @__PURE__ */ new Map();
2280
+ if (((_app_imagePicker2 = app.imagePicker) === null || _app_imagePicker2 === void 0 ? void 0 : _app_imagePicker2.camera) !== void 0) {
2281
+ usage.set("NSCameraUsageDescription", app.imagePicker.camera);
2282
+ }
2283
+ if (((_app_imagePicker3 = app.imagePicker) === null || _app_imagePicker3 === void 0 ? void 0 : _app_imagePicker3.microphone) !== void 0) {
2284
+ usage.set("NSMicrophoneUsageDescription", app.imagePicker.microphone);
2285
+ }
2286
+ if (app.photoLibrary !== void 0) {
2287
+ if (app.photoLibrary.addOnly !== void 0) {
2288
+ usage.set("NSPhotoLibraryAddUsageDescription", app.photoLibrary.addOnly);
2289
+ }
2290
+ if (app.photoLibrary.readWrite !== void 0) {
2291
+ usage.set("NSPhotoLibraryUsageDescription", app.photoLibrary.readWrite);
2292
+ }
2293
+ }
2294
+ if (app.contacts !== void 0) {
2295
+ usage.set("NSContactsUsageDescription", app.contacts.usage);
2296
+ }
2297
+ if (app.calendar !== void 0) {
2298
+ if (app.calendar.usage !== void 0) {
2299
+ usage.set("NSCalendarsFullAccessUsageDescription", app.calendar.usage);
2300
+ }
2301
+ if (app.calendar.remindersUsage !== void 0) {
2302
+ usage.set("NSRemindersFullAccessUsageDescription", app.calendar.remindersUsage);
2303
+ }
2304
+ }
2305
+ if (app.location !== void 0) {
2306
+ usage.set("NSLocationWhenInUseUsageDescription", app.location.whenInUse);
2307
+ if (app.location.alwaysAndWhenInUse !== void 0) {
2308
+ usage.set("NSLocationAlwaysAndWhenInUseUsageDescription", app.location.alwaysAndWhenInUse);
2309
+ }
2310
+ }
2311
+ if (app.pedometer !== void 0) {
2312
+ usage.set("NSMotionUsageDescription", app.pedometer.usage);
2313
+ }
2314
+ if (((_app_ios14 = app.ios) === null || _app_ios14 === void 0 ? void 0 : _app_ios14.faceIdUsageDescription) !== void 0) {
2315
+ usage.set("NSFaceIDUsageDescription", app.ios.faceIdUsageDescription);
2316
+ }
2317
+ if (app.speech !== void 0) {
2318
+ usage.set("NSSpeechRecognitionUsageDescription", app.speech.recognition);
2319
+ usage.set("NSMicrophoneUsageDescription", app.speech.microphone);
2320
+ }
2321
+ if (((_app_audio4 = app.audio) === null || _app_audio4 === void 0 ? void 0 : _app_audio4.microphone) !== void 0) {
2322
+ usage.set("NSMicrophoneUsageDescription", app.audio.microphone);
2323
+ }
2324
+ var additions = [];
2325
+ var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
2326
+ try {
2327
+ var _loop1 = function() {
2328
+ var [key, text] = _step2.value;
2329
+ var existing = new RegExp(`(<key>${key}</key>\\s*<string>)[^<]*(</string>)`);
2330
+ if (existing.test(rendered)) {
2331
+ rendered = rendered.replace(existing, function(_match, before, after) {
2332
+ return `${before}${escapeXml(text)}${after}`;
2333
+ });
2334
+ } else {
2335
+ additions.push([key, text]);
2336
+ }
2337
+ };
2338
+ for (var _iterator2 = usage[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) _loop1();
2339
+ } catch (err) {
2340
+ _didIteratorError2 = true;
2341
+ _iteratorError2 = err;
2342
+ } finally {
2343
+ try {
2344
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
2345
+ _iterator2.return();
2346
+ }
2347
+ } finally {
2348
+ if (_didIteratorError2) {
2349
+ throw _iteratorError2;
2350
+ }
1338
2351
  }
1339
- rendered = rendered.replace(anchor6, ` <key>NSCameraUsageDescription</key>
1340
- <string>${escapeXml(app.imagePicker.camera)}</string>
1341
- ${anchor6}`);
1342
2352
  }
2353
+ if (additions.length) {
2354
+ var anchor13 = " <key>LSRequiresIPhoneOS</key>";
2355
+ if (!rendered.includes(anchor13)) {
2356
+ throw new Error(`[vxrn] cannot stamp ${additions[0][0]}: expected LSRequiresIPhoneOS in Info.plist`);
2357
+ }
2358
+ rendered = rendered.replace(anchor13, `${additions.map(function(param) {
2359
+ var [key, text] = param;
2360
+ return ` <key>${key}</key>
2361
+ <string>${escapeXml(text)}</string>
2362
+ `;
2363
+ }).join("")}${anchor13}`);
2364
+ }
2365
+ rendered = rendered.replace(/\t<key>NS\w+UsageDescription<\/key>\s*<string><\/string>\n/g, "");
1343
2366
  rendered = patchIosInfoPlistSceneManifest(rendered);
1344
2367
  }
1345
2368
  if (platform === "ios" && relativePath.endsWith("/AppDelegate.swift")) {
1346
- rendered = patchIosAppDelegateSceneLifecycle(rendered, appName);
2369
+ var _app_ios15, _app_ios16;
2370
+ rendered = patchIosAppDelegateSceneLifecycle(rendered, appName, !!((_app_ios15 = app.ios) === null || _app_ios15 === void 0 ? void 0 : _app_ios15.backgroundTasks), !!((_app_ios16 = app.ios) === null || _app_ios16 === void 0 ? void 0 : _app_ios16.appIntents));
2371
+ rendered = nativeProjectPatches.holdLaunchScreenOverRootView(rendered);
2372
+ var bundleURLProvider = "RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: \"index\")";
2373
+ if (!rendered.includes(bundleURLProvider)) {
2374
+ throw new Error("[vxrn] cannot request hermes dev bytecode: expected the template bundle URL provider");
2375
+ }
2376
+ rendered = rendered.replace(bundleURLProvider, `guard let bundleURL = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") else { return nil }
2377
+ if bundleURL.isFileURL { return bundleURL }
2378
+ var components = URLComponents(url: bundleURL, resolvingAgainstBaseURL: false)!
2379
+ components.queryItems!.append(URLQueryItem(name: "bytecode", value: "hermes"))
2380
+ return components.url`);
2381
+ if (app.updates !== void 0) {
2382
+ rendered = nativeProjectPatches.pointReleaseBundleURLAtOneUpdates(rendered);
2383
+ }
1347
2384
  }
1348
- if (platform === "ios" && ((_app_ios = app.ios) === null || _app_ios === void 0 ? void 0 : _app_ios.deploymentTarget)) {
2385
+ if (platform === "ios" && ((_app_ios2 = app.ios) === null || _app_ios2 === void 0 ? void 0 : _app_ios2.deploymentTarget)) {
1349
2386
  rendered = rendered.replace("platform :ios, min_ios_version_supported", `platform :ios, '${app.ios.deploymentTarget}'`).replace(/IPHONEOS_DEPLOYMENT_TARGET = \d+(?:\.\d+)?;/g, `IPHONEOS_DEPLOYMENT_TARGET = ${app.ios.deploymentTarget};`);
1350
2387
  if (relativePath === "Podfile") {
1351
2388
  rendered = rendered.replace(" )\n end\nend", ` )
@@ -1360,44 +2397,58 @@ end`);
1360
2397
  }
1361
2398
  }
1362
2399
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1363
- var _app_notifications3, _app_ios6, _app_ios7;
1364
- rendered = patchIosBundlePhase(rendered);
2400
+ var _app_updates, _app_ios17, _app_ios18, _app_ios19;
2401
+ rendered = patchIosBundlePhase(rendered, (_app_updates = app.updates) === null || _app_updates === void 0 ? void 0 : _app_updates.runtimeVersion);
1365
2402
  rendered = patchIosPbxprojSceneDelegate(rendered, appName);
1366
- if (((_app_notifications3 = app.notifications) === null || _app_notifications3 === void 0 ? void 0 : _app_notifications3.push) === true && !((_app_ios6 = app.ios) === null || _app_ios6 === void 0 ? void 0 : _app_ios6.widgets)) {
1367
- rendered = patchIosPbxprojPushEntitlements(rendered, appName);
2403
+ if ((_app_ios17 = app.ios) === null || _app_ios17 === void 0 ? void 0 : _app_ios17.appIntents) rendered = patchIosPbxprojAppIntents(rendered, appName);
2404
+ rendered = patchIosPbxprojOneBridgingHeader(rendered, appName);
2405
+ if (Object.keys(appEntitlements(app)).length && !((_app_ios18 = app.ios) === null || _app_ios18 === void 0 ? void 0 : _app_ios18.widgets)) {
2406
+ rendered = patchIosPbxprojAppEntitlements(rendered, appName);
2407
+ }
2408
+ if ((_app_ios19 = app.ios) === null || _app_ios19 === void 0 ? void 0 : _app_ios19.widgets) rendered = patchIosPbxprojWidgets(rendered, app);
2409
+ if (iosResourceFiles(app).length) {
2410
+ rendered = patchIosPbxprojResources(rendered, appName, iosResourceFiles(app));
1368
2411
  }
1369
- if ((_app_ios7 = app.ios) === null || _app_ios7 === void 0 ? void 0 : _app_ios7.widgets) rendered = patchIosPbxprojWidgets(rendered, app);
1370
2412
  }
1371
2413
  if (platform === "ios" && relativePath === "Podfile") {
1372
- var _app_ios8, _app_ios9, _app_ios10;
1373
- if ((_app_ios8 = app.ios) === null || _app_ios8 === void 0 ? void 0 : _app_ios8.ccache) rendered = `ENV['USE_CCACHE'] ||= '1'
2414
+ var _app_ios20, _app_ios21, _app_ios22;
2415
+ if ((_app_ios20 = app.ios) === null || _app_ios20 === void 0 ? void 0 : _app_ios20.ccache) rendered = `ENV['USE_CCACHE'] ||= '1'
1374
2416
  ${rendered}`;
1375
- if ((_app_ios9 = app.ios) === null || _app_ios9 === void 0 ? void 0 : _app_ios9.useFrameworks) {
2417
+ if ((_app_ios21 = app.ios) === null || _app_ios21 === void 0 ? void 0 : _app_ios21.useFrameworks) {
1376
2418
  rendered = rendered.replace(/^(platform :ios, .+)$/m, `$1
1377
2419
  use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1378
2420
  }
1379
- if ((_app_ios10 = app.ios) === null || _app_ios10 === void 0 ? void 0 : _app_ios10.screensGamma) {
2421
+ if ((_app_ios22 = app.ios) === null || _app_ios22 === void 0 ? void 0 : _app_ios22.screensGamma) {
1380
2422
  rendered = nativeProjectPatches.injectReactNativeScreensGammaIntoPodfile(rendered);
1381
2423
  }
1382
2424
  rendered = nativeProjectPatches.injectFmtCxx17FixIntoPodfile(rendered);
2425
+ rendered = nativeProjectPatches.injectWebGPUHeaderPathsIntoPodfile(rendered);
1383
2426
  rendered = nativeProjectPatches.injectOneSwiftPackagesIntoPodfile(rendered);
1384
2427
  if (nitroWebImage) rendered = nativeProjectPatches.injectNitroWebImageModularHeaderIntoPodfile(rendered);
1385
2428
  rendered = nativeProjectPatches.injectHermesMinificationPatchIntoPodfile(rendered);
2429
+ var nativeModulesCall = "config = use_native_modules!";
2430
+ if (rendered.split(nativeModulesCall).length !== 2) {
2431
+ throw new Error("[vxrn] expected one iOS native module discovery call");
2432
+ }
2433
+ rendered = rendered.replace(nativeModulesCall, `config = use_native_modules!(['node', '-e', "process.argv=['', '', 'config'];require(require('module').createRequire(require.resolve('vxrn/package.json')).resolve('@react-native-community/cli')).run()"])`);
1386
2434
  if (!rendered.includes("[vxrn/one] fmt c++17 fix") || !rendered.includes("[vxrn/one] minify iOS Hermes Release bundle input")) {
1387
2435
  throw new Error("[vxrn] failed to apply required iOS Podfile patches");
1388
2436
  }
1389
2437
  }
1390
2438
  if (platform === "android" && relativePath === "app/build.gradle") {
1391
- var _app_android3;
2439
+ var _app_android11;
1392
2440
  rendered = nativeProjectPatches.replaceAppBuildGradleReactBlock(rendered);
1393
2441
  rendered = nativeProjectPatches.addDepsPatchToAppBuildGradle(rendered);
1394
2442
  if (!rendered.includes("entryFile = file(\"../../package.json\")") || !rendered.includes("[vxrn/one] ensure patches are applied")) {
1395
2443
  throw new Error("[vxrn] failed to apply required Android Gradle patches");
1396
2444
  }
2445
+ if (app.updates !== void 0) {
2446
+ rendered = patchAndroidBuildGradleUpdatesManifest(rendered, app.updates.runtimeVersion);
2447
+ }
1397
2448
  if (app.version !== void 0) {
1398
2449
  rendered = rendered.replace(/versionName "[^"]*"/g, `versionName "${app.version}"`);
1399
2450
  }
1400
- if (((_app_android3 = app.android) === null || _app_android3 === void 0 ? void 0 : _app_android3.versionCode) !== void 0) {
2451
+ if (((_app_android11 = app.android) === null || _app_android11 === void 0 ? void 0 : _app_android11.versionCode) !== void 0) {
1401
2452
  rendered = rendered.replace(/versionCode \d+/g, `versionCode ${app.android.versionCode}`);
1402
2453
  }
1403
2454
  }
@@ -1407,9 +2458,76 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1407
2458
  throw new Error("[vxrn] expected two React Native Gradle plugin paths");
1408
2459
  }
1409
2460
  rendered = rendered.replace(hardcodedGradlePlugin, `includeBuild(new File(["node", "--print", "require('module').createRequire(require.resolve('react-native/package.json')).resolve('@react-native/gradle-plugin/package.json')"].execute(null, settingsDir).text.trim()).parentFile.canonicalPath)`);
2461
+ var autolinkCommand = "ex.autolinkLibrariesFromCommand()";
2462
+ if (rendered.split(autolinkCommand).length !== 2) {
2463
+ throw new Error("[vxrn] expected one React Native autolinking command");
2464
+ }
2465
+ rendered = rendered.replace(autolinkCommand, `ex.autolinkLibrariesFromCommand(["node", ["node", "--print", "require('module').createRequire(require.resolve('vxrn/package.json')).resolve('@react-native-community/cli/build/bin.js')"].execute(null, settingsDir).text.trim(), "config"])`);
1410
2466
  }
1411
- if (platform === "android" && ((_app_android2 = app.android) === null || _app_android2 === void 0 ? void 0 : _app_android2.minSdk) !== void 0) {
1412
- rendered = rendered.replace(/minSdkVersion = \d+/g, `minSdkVersion = ${app.android.minSdk}`);
2467
+ if (platform === "android" && relativePath === "app/build.gradle" && ((_app_android5 = app.android) === null || _app_android5 === void 0 ? void 0 : _app_android5.minify)) {
2468
+ var minify = "def enableProguardInReleaseBuilds = false";
2469
+ var minifyEnabled = "minifyEnabled enableProguardInReleaseBuilds";
2470
+ if (!rendered.includes(minify) || !rendered.includes(minifyEnabled)) {
2471
+ throw new Error("[vxrn] prebuild template app/build.gradle lost its proguard switch");
2472
+ }
2473
+ rendered = rendered.replace(minify, "def enableProguardInReleaseBuilds = true");
2474
+ if (app.android.shrinkResources) {
2475
+ rendered = rendered.replace(minifyEnabled, `${minifyEnabled}
2476
+ shrinkResources true`);
2477
+ }
2478
+ }
2479
+ if (platform === "android" && ((_app_android6 = app.android) === null || _app_android6 === void 0 ? void 0 : _app_android6.googleServicesFile)) {
2480
+ var edits = [[
2481
+ "build.gradle",
2482
+ "classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")",
2483
+ ` classpath("com.google.gms:google-services:${GOOGLE_SERVICES_VERSION}")`
2484
+ ], [
2485
+ "app/build.gradle",
2486
+ "apply plugin: \"com.facebook.react\"",
2487
+ "apply plugin: \"com.google.gms.google-services\""
2488
+ ]];
2489
+ var _iteratorNormalCompletion3 = true, _didIteratorError3 = false, _iteratorError3 = void 0;
2490
+ try {
2491
+ for (var _iterator3 = edits[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
2492
+ var [file, anchor14, insertion] = _step3.value;
2493
+ if (relativePath !== file) continue;
2494
+ var next = insertAfterLine(rendered, anchor14, insertion);
2495
+ if (next === rendered) {
2496
+ throw new Error(`[vxrn] prebuild template ${file} lost its ${anchor14} anchor`);
2497
+ }
2498
+ rendered = next;
2499
+ }
2500
+ } catch (err) {
2501
+ _didIteratorError3 = true;
2502
+ _iteratorError3 = err;
2503
+ } finally {
2504
+ try {
2505
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
2506
+ _iterator3.return();
2507
+ }
2508
+ } finally {
2509
+ if (_didIteratorError3) {
2510
+ throw _iteratorError3;
2511
+ }
2512
+ }
2513
+ }
2514
+ }
2515
+ if (platform === "android" && relativePath === "app/proguard-rules.pro" && ((_app_android7 = app.android) === null || _app_android7 === void 0 ? void 0 : _app_android7.proguardRules)) {
2516
+ rendered = `${rendered.trimEnd()}
2517
+
2518
+ ${app.android.proguardRules.trim()}
2519
+ `;
2520
+ }
2521
+ for (var _i = 0, _iter = [
2522
+ ["minSdk", "minSdkVersion"],
2523
+ ["targetSdk", "targetSdkVersion"],
2524
+ ["compileSdk", "compileSdkVersion"]
2525
+ ]; _i < _iter.length; _i++) {
2526
+ var [field, setting] = _iter[_i];
2527
+ var _app_android12;
2528
+ var value1 = platform === "android" ? (_app_android12 = app.android) === null || _app_android12 === void 0 ? void 0 : _app_android12[field] : void 0;
2529
+ if (value1 === void 0) continue;
2530
+ rendered = rendered.replace(new RegExp(`${setting} = \\d+`, "g"), `${setting} = ${value1}`);
1413
2531
  }
1414
2532
  }
1415
2533
  return {
@@ -1417,14 +2535,14 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1417
2535
  content: rendered
1418
2536
  };
1419
2537
  }
1420
- var generateForPlatform = async function(root, platform, app) {
2538
+ var generateForPlatform = async function generateForPlatform2(root, platform, app) {
1421
2539
  var outDir = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : path.resolve(root, platform);
1422
2540
  var _ref, _ref1;
1423
2541
  var _walkModule_default;
1424
2542
  validatePrebuildApp(app, platform);
1425
2543
  var dest = outDir;
1426
2544
  var require2 = module.createRequire(root + "/");
1427
- var importPath = require2.resolve("@react-native-community/cli/build/tools/walk.js", { paths: [root] });
2545
+ var importPath = requireVxrn.resolve("@react-native-community/cli/build/tools/walk.js");
1428
2546
  var src = path.join(path.dirname(require2.resolve("@react-native-community/template/template/package.json", { paths: [root] })), platform);
1429
2547
  var walkModule = await import(pathToFileURL(importPath).href);
1430
2548
  var walkFn = (_ref = (_ref1 = walkModule === null || walkModule === void 0 ? void 0 : (_walkModule_default = walkModule.default) === null || _walkModule_default === void 0 ? void 0 : _walkModule_default.default) !== null && _ref1 !== void 0 ? _ref1 : walkModule === null || walkModule === void 0 ? void 0 : walkModule.default) !== null && _ref !== void 0 ? _ref : walkModule;
@@ -1486,48 +2604,210 @@ var generateForPlatform = async function(root, platform, app) {
1486
2604
  platform,
1487
2605
  app
1488
2606
  });
2607
+ if (platform === "android") await generateAdaptiveIcon({
2608
+ root,
2609
+ dest,
2610
+ app
2611
+ });
1489
2612
  await generateSplashScreen({
1490
2613
  root,
1491
2614
  dest,
1492
2615
  platform,
1493
2616
  app
1494
2617
  });
2618
+ if (platform === "ios") generateAccentColor({
2619
+ dest,
2620
+ app
2621
+ });
2622
+ copyAppResources({
2623
+ root,
2624
+ dest,
2625
+ platform,
2626
+ app
2627
+ });
1495
2628
  generateSceneDelegate({
1496
2629
  dest,
1497
2630
  platform,
1498
2631
  app
1499
2632
  });
2633
+ generateIosAppIntents(dest, platform, app);
2634
+ if (platform === "ios") generateOneBridgingHeader(dest, app);
1500
2635
  if (platform === "ios") generateIosWidgets(dest, app);
1501
- if (platform === "ios") generateSwiftPackages({
2636
+ if (platform === "ios") await generateSwiftPackages({
2637
+ root,
2638
+ dest
2639
+ });
2640
+ if (platform === "android") await generateKotlinSources({
1502
2641
  root,
1503
2642
  dest
1504
2643
  });
1505
2644
  };
1506
- function generateSwiftPackages(param) {
2645
+ var KOTLIN_IMPORT_ARTIFACTS = [{
2646
+ importPrefix: "androidx.compose.material.icons",
2647
+ artifact: "androidx.compose.material:material-icons-core",
2648
+ versionKey: "materialIconsVersion",
2649
+ version: "1.7.6"
2650
+ }];
2651
+ function kotlinSourceImports(dir) {
2652
+ var imports = /* @__PURE__ */ new Set();
2653
+ if (!FSExtra.existsSync(dir)) return imports;
2654
+ var visit = function visit1(entry) {
2655
+ if (FSExtra.statSync(entry).isDirectory()) {
2656
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
2657
+ try {
2658
+ for (var _iterator = FSExtra.readdirSync(entry)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
2659
+ var child = _step.value;
2660
+ visit(path.join(entry, child));
2661
+ }
2662
+ } catch (err) {
2663
+ _didIteratorError = true;
2664
+ _iteratorError = err;
2665
+ } finally {
2666
+ try {
2667
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2668
+ _iterator.return();
2669
+ }
2670
+ } finally {
2671
+ if (_didIteratorError) {
2672
+ throw _iteratorError;
2673
+ }
2674
+ }
2675
+ }
2676
+ return;
2677
+ }
2678
+ if (!entry.endsWith(".kt")) return;
2679
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
2680
+ try {
2681
+ for (var _iterator1 = FSExtra.readFileSync(entry, "utf8").split("\n")[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
2682
+ var line = _step1.value;
2683
+ var match = /^\s*import\s+([A-Za-z0-9_.]+)/.exec(line);
2684
+ if (match) imports.add(match[1]);
2685
+ }
2686
+ } catch (err) {
2687
+ _didIteratorError1 = true;
2688
+ _iteratorError1 = err;
2689
+ } finally {
2690
+ try {
2691
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2692
+ _iterator1.return();
2693
+ }
2694
+ } finally {
2695
+ if (_didIteratorError1) {
2696
+ throw _iteratorError1;
2697
+ }
2698
+ }
2699
+ }
2700
+ };
2701
+ visit(dir);
2702
+ return imports;
2703
+ }
2704
+ function enableAppComposeIntegration(dest) {
2705
+ var rootBuildGradlePath = path.join(dest, "build.gradle");
2706
+ if (FSExtra.existsSync(rootBuildGradlePath)) {
2707
+ var content = FSExtra.readFileSync(rootBuildGradlePath, "utf8");
2708
+ var composePluginClasspath = " classpath(\"org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin:$kotlinVersion\")";
2709
+ if (!content.includes("org.jetbrains.kotlin.plugin.compose")) {
2710
+ var anchor = content.includes("classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")") ? "classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")" : "classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin\"";
2711
+ content = insertAfterLine(content, anchor, composePluginClasspath);
2712
+ FSExtra.writeFileSync(rootBuildGradlePath, content, "utf8");
2713
+ }
2714
+ }
2715
+ var appBuildGradlePath = path.join(dest, "app/build.gradle");
2716
+ if (FSExtra.existsSync(appBuildGradlePath)) {
2717
+ var content1 = FSExtra.readFileSync(appBuildGradlePath, "utf8");
2718
+ if (!content1.includes("org.jetbrains.kotlin.plugin.compose")) {
2719
+ var pluginAnchor = content1.includes("apply plugin: \"org.jetbrains.kotlin.android\"") ? "apply plugin: \"org.jetbrains.kotlin.android\"" : "apply plugin: 'org.jetbrains.kotlin.android'";
2720
+ content1 = insertAfterLine(content1, pluginAnchor, "apply plugin: \"org.jetbrains.kotlin.plugin.compose\"");
2721
+ }
2722
+ if (!content1.includes("compose true")) {
2723
+ content1 = insertAfterLine(content1, "android {", " buildFeatures {\n compose true\n }");
2724
+ }
2725
+ if (!content1.includes("androidx.compose.ui:ui")) {
2726
+ var composeDeps = [
2727
+ " def composeUiVersion = rootProject.ext.has(\"composeUiVersion\") ? rootProject.ext.get(\"composeUiVersion\") : \"1.11.4\"",
2728
+ " def material3Version = rootProject.ext.has(\"material3Version\") ? rootProject.ext.get(\"material3Version\") : \"1.5.0-alpha17\"",
2729
+ " implementation \"androidx.compose.ui:ui:$composeUiVersion\"",
2730
+ " implementation \"androidx.compose.foundation:foundation:$composeUiVersion\"",
2731
+ " implementation \"androidx.compose.material3:material3:$material3Version\"",
2732
+ " def navigationComposeVersion = rootProject.ext.has(\"navigationComposeVersion\") ? rootProject.ext.get(\"navigationComposeVersion\") : \"2.10.2\"",
2733
+ " implementation \"androidx.navigation:navigation-compose:$navigationComposeVersion\""
2734
+ ].join("\n");
2735
+ var depsAnchor = content1.includes("implementation(\"com.facebook.react:react-android\")") ? "implementation(\"com.facebook.react:react-android\")" : "implementation \"com.facebook.react:react-android\"";
2736
+ content1 = insertAfterLine(content1, depsAnchor, composeDeps);
2737
+ }
2738
+ var imports = kotlinSourceImports(path.join(dest, "app/src/main/java/one/source"));
2739
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
2740
+ try {
2741
+ var _loop = function() {
2742
+ var rule = _step.value;
2743
+ var needed = [...imports].some(function(name) {
2744
+ return name === rule.importPrefix || name.startsWith(`${rule.importPrefix}.`);
2745
+ });
2746
+ if (!needed || content1.includes(rule.artifact)) return "continue";
2747
+ var reactAnchor = content1.includes("implementation(\"com.facebook.react:react-android\")") ? "implementation(\"com.facebook.react:react-android\")" : "implementation \"com.facebook.react:react-android\"";
2748
+ var anchor2 = content1.includes("androidx.compose.material3:material3") ? "androidx.compose.material3:material3" : reactAnchor;
2749
+ content1 = insertAfterLine(content1, anchor2, [` def ${rule.versionKey} = rootProject.ext.has("${rule.versionKey}") ? rootProject.ext.get("${rule.versionKey}") : "${rule.version}"`, ` implementation "${rule.artifact}:$${rule.versionKey}"`].join("\n"));
2750
+ };
2751
+ for (var _iterator = KOTLIN_IMPORT_ARTIFACTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
2752
+ } catch (err) {
2753
+ _didIteratorError = true;
2754
+ _iteratorError = err;
2755
+ } finally {
2756
+ try {
2757
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2758
+ _iterator.return();
2759
+ }
2760
+ } finally {
2761
+ if (_didIteratorError) {
2762
+ throw _iteratorError;
2763
+ }
2764
+ }
2765
+ }
2766
+ FSExtra.writeFileSync(appBuildGradlePath, content1, "utf8");
2767
+ }
2768
+ }
2769
+ async function generateKotlinSources(param) {
1507
2770
  var { root, dest } = param;
2771
+ var _ref;
2772
+ var _manifest_workspaces;
1508
2773
  var skip = /* @__PURE__ */ new Set([
1509
2774
  "node_modules",
1510
2775
  "ios",
1511
2776
  "android",
1512
2777
  "dist",
1513
2778
  "types",
1514
- "build"
2779
+ "build",
2780
+ "tests",
2781
+ "__tests__",
2782
+ "scripts",
2783
+ "evidence"
1515
2784
  ]);
1516
- var packageDirs = [];
1517
- var walk = function(dir) {
1518
- var entries = FSExtra.readdirSync(dir, { withFileTypes: true });
1519
- if (entries.some(function(entry2) {
1520
- return entry2.isFile() && entry2.name === "Package.swift";
1521
- })) {
1522
- packageDirs.push(dir);
1523
- return;
1524
- }
2785
+ var sources = [];
2786
+ var manifest = FSExtra.existsSync(path.join(root, "package.json")) ? FSExtra.readJsonSync(path.join(root, "package.json")) : {};
2787
+ var workspacePatterns = Array.isArray(manifest.workspaces) ? manifest.workspaces : (_ref = (_manifest_workspaces = manifest.workspaces) === null || _manifest_workspaces === void 0 ? void 0 : _manifest_workspaces.packages) !== null && _ref !== void 0 ? _ref : [];
2788
+ var { default: glob } = await import("fast-glob");
2789
+ var workspaceRoots = new Set(glob.sync(workspacePatterns, {
2790
+ cwd: root,
2791
+ absolute: true,
2792
+ onlyDirectories: true,
2793
+ ignore: [
2794
+ "**/node_modules/**",
2795
+ "**/ios/**",
2796
+ "**/android/**"
2797
+ ]
2798
+ }).map(function(directory) {
2799
+ return path.resolve(directory);
2800
+ }));
2801
+ var collect = function collect1(dir) {
2802
+ if (dir !== root && FSExtra.existsSync(path.join(dir, "package.json")) && !workspaceRoots.has(dir)) return;
1525
2803
  var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1526
2804
  try {
1527
- for (var _iterator2 = entries[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
2805
+ for (var _iterator2 = FSExtra.readdirSync(dir, { withFileTypes: true })[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
1528
2806
  var entry = _step2.value;
1529
- if (!entry.isDirectory() || entry.name.startsWith(".") || skip.has(entry.name)) continue;
1530
- walk(path.join(dir, entry.name));
2807
+ if (entry.name.startsWith(".") || skip.has(entry.name)) continue;
2808
+ var source2 = path.join(dir, entry.name);
2809
+ if (entry.isDirectory()) collect(source2);
2810
+ else if (entry.isFile() && entry.name.endsWith(".kt")) sources.push(source2);
1531
2811
  }
1532
2812
  } catch (err) {
1533
2813
  _didIteratorError2 = true;
@@ -1544,15 +2824,65 @@ function generateSwiftPackages(param) {
1544
2824
  }
1545
2825
  }
1546
2826
  };
1547
- walk(root);
2827
+ collect(root);
2828
+ var output = path.join(dest, "app/src/main/java/one/source");
2829
+ FSExtra.removeSync(output);
2830
+ if (sources.length === 0) return;
2831
+ var { kotlinSourceId, renderKotlinSourceGlue, writeNativeSourceDeclaration } = await import("../utils/nativeSourceContract.native.js");
2832
+ var hasViews = false;
2833
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
2834
+ try {
2835
+ for (var _iterator = sources[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
2836
+ var source = _step.value;
2837
+ var id = kotlinSourceId(root, source);
2838
+ var target = path.join(output, id);
2839
+ FSExtra.mkdirSync(target, { recursive: true });
2840
+ FSExtra.copyFileSync(source, path.join(target, path.basename(source)));
2841
+ var contract = writeNativeSourceDeclaration(source);
2842
+ if (contract.views.length > 0) hasViews = true;
2843
+ if (contract.modules.length > 0 || contract.views.length > 0) {
2844
+ FSExtra.writeFileSync(path.join(target, `OneNativeSource_${id}.kt`), renderKotlinSourceGlue(id, contract).source);
2845
+ }
2846
+ }
2847
+ } catch (err) {
2848
+ _didIteratorError = true;
2849
+ _iteratorError = err;
2850
+ } finally {
2851
+ try {
2852
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2853
+ _iterator.return();
2854
+ }
2855
+ } finally {
2856
+ if (_didIteratorError) {
2857
+ throw _iteratorError;
2858
+ }
2859
+ }
2860
+ }
2861
+ if (hasViews) {
2862
+ enableAppComposeIntegration(dest);
2863
+ }
2864
+ }
2865
+ async function generateSwiftPackages(param) {
2866
+ var { root, dest } = param;
2867
+ var skip = /* @__PURE__ */ new Set([
2868
+ "node_modules",
2869
+ "ios",
2870
+ "android",
2871
+ "dist",
2872
+ "types",
2873
+ "build"
2874
+ ]);
2875
+ var packages = swiftPackageDirectories(root);
2876
+ if (packages.size === 0) return;
2877
+ var { swiftPodManifest, writeSwiftPackageArtifacts } = await import("../utils/nativeSourceContract.native.js");
1548
2878
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
1549
2879
  try {
1550
2880
  var _loop = function() {
1551
- var packageDir = _step.value;
1552
- var id = swiftPackageId(packageDir);
2881
+ var [id, packageDir] = _step.value;
1553
2882
  var podDir = path.join(dest, "OneSwiftPackages", id);
2883
+ var manifest = swiftPodManifest(path.join(packageDir, "Package.swift"), FSExtra.readFileSync(path.join(packageDir, "Package.swift"), "utf8"));
1554
2884
  var sources = [];
1555
- var collect = function(dir) {
2885
+ var collect = function collect1(dir) {
1556
2886
  var _iteratorNormalCompletion3 = true, _didIteratorError3 = false, _iteratorError3 = void 0;
1557
2887
  try {
1558
2888
  for (var _iterator3 = FSExtra.readdirSync(dir, { withFileTypes: true })[Symbol.iterator](), _step2; !(_iteratorNormalCompletion3 = (_step2 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
@@ -1578,6 +2908,16 @@ function generateSwiftPackages(param) {
1578
2908
  }
1579
2909
  };
1580
2910
  collect(packageDir);
2911
+ var artifacts = writeSwiftPackageArtifacts(packageDir);
2912
+ var contracts = artifacts.contracts;
2913
+ var hasView = contracts.some(function(contract) {
2914
+ return contract.defaultView;
2915
+ });
2916
+ if (contracts.filter(function(contract) {
2917
+ return contract.defaultView;
2918
+ }).length > 1) {
2919
+ throw new Error(`[vxrn] swift package ${packageDir} has more than one @main type`);
2920
+ }
1581
2921
  var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1582
2922
  try {
1583
2923
  for (var _iterator2 = sources[Symbol.iterator](), _step1; !(_iteratorNormalCompletion2 = (_step1 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
@@ -1600,6 +2940,9 @@ function generateSwiftPackages(param) {
1600
2940
  }
1601
2941
  }
1602
2942
  }
2943
+ if (artifacts.glue) {
2944
+ FSExtra.writeFileSync(path.join(podDir, "Sources", "OneNativeSource.generated.swift"), artifacts.glue);
2945
+ }
1603
2946
  FSExtra.writeFileSync(path.join(podDir, `${id}.podspec`), `Pod::Spec.new do |s|
1604
2947
  s.name = '${id}'
1605
2948
  s.version = '0.0.0'
@@ -1608,15 +2951,15 @@ function generateSwiftPackages(param) {
1608
2951
  s.license = 'MIT'
1609
2952
  s.author = 'one'
1610
2953
  s.source = { :path => '.' }
1611
- s.swift_version = '6.0'
2954
+ s.swift_version = '${manifest.languageMode}.0'
1612
2955
  s.source_files = 'Sources/**/*.swift', 'Register.m'
1613
- s.dependency 'VxrnNative'
2956
+ s.dependency 'One'
1614
2957
  s.pod_target_xcconfig = {
1615
- 'OTHER_SWIFT_FLAGS' => '$(inherited) -cxx-interoperability-mode=default -Xcc -std=c++20 -Xfrontend -import-module -Xfrontend VxrnNative -Xfrontend -entry-point-function-name -Xfrontend ${id}_main',
2958
+ 'OTHER_SWIFT_FLAGS' => '$(inherited) -cxx-interoperability-mode=default -Xcc -std=c++20 -Xfrontend -import-module -Xfrontend One${manifest.mainActorIsolation ? " -default-isolation MainActor" : ""}${hasView ? ` -Xfrontend -entry-point-function-name -Xfrontend ${id}_main` : ""}',
1616
2959
  }
1617
2960
  end
1618
2961
  `);
1619
- FSExtra.writeFileSync(path.join(podDir, "Register.m"), `#import <Foundation/Foundation.h>
2962
+ FSExtra.writeFileSync(path.join(podDir, "Register.m"), hasView ? `#import <Foundation/Foundation.h>
1620
2963
 
1621
2964
  extern int ${id}_main(int argc, char **argv);
1622
2965
  extern void OneSwiftRegisterPackage(const char *name, int (*entry)(int, char **));
@@ -1629,9 +2972,9 @@ extern void OneSwiftRegisterPackage(const char *name, int (*entry)(int, char **)
1629
2972
  OneSwiftRegisterPackage("${id}", ${id}_main);
1630
2973
  }
1631
2974
  @end
1632
- `);
2975
+ ` : "#import <Foundation/Foundation.h>\n");
1633
2976
  };
1634
- for (var _iterator = packageDirs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
2977
+ for (var _iterator = packages[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
1635
2978
  } catch (err) {
1636
2979
  _didIteratorError = true;
1637
2980
  _iteratorError = err;
@@ -1655,15 +2998,14 @@ function applyAndroidDependencyPatches(args) {
1655
2998
  return;
1656
2999
  }
1657
3000
  var activityPath = path.join(root, "android", "app", "src", "main", "java", ...app.android.applicationId.split("."), "MainActivity.kt");
1658
- var rendered = nativeProjectPatches.addReactNativeScreensFix(FSExtra.readFileSync(activityPath, "utf8"));
3001
+ var rendered = nativeProjectPatches.holdLaunchScreenInMainActivity(nativeProjectPatches.addReactNativeScreensFix(FSExtra.readFileSync(activityPath, "utf8")));
1659
3002
  if (!rendered.includes("RNScreensFragmentFactory")) {
1660
3003
  throw new Error("[vxrn] failed to apply the react-native-screens activity patch");
1661
3004
  }
1662
3005
  FSExtra.writeFileSync(activityPath, rendered);
1663
3006
  }
1664
3007
  async function getNativeDependencyInventory(root) {
1665
- var require2 = module.createRequire(root + "/");
1666
- var cliConfigPath = require2.resolve("@react-native-community/cli-config", { paths: [root] });
3008
+ var cliConfigPath = requireVxrn.resolve("@react-native-community/cli-config");
1667
3009
  var cliConfig = await import(pathToFileURL(cliConfigPath).href);
1668
3010
  var config = await cliConfig.loadConfigAsync({ projectRoot: root });
1669
3011
  var inventory = [];
@@ -1710,12 +3052,19 @@ async function getNativeDependencyInventory(root) {
1710
3052
  function installNativeDependencies(args) {
1711
3053
  var { root, platform } = args;
1712
3054
  if (!platform || platform === "ios") {
1713
- execFileSync("pod", ["install", `--project-directory=${path.join(root, "ios")}`], { stdio: "inherit" });
3055
+ execFileSync("pod", ["install", `--project-directory=${path.join(root, "ios")}`], {
3056
+ stdio: "inherit",
3057
+ env: {
3058
+ ...process.env,
3059
+ LC_ALL: "en_US.UTF-8",
3060
+ RCT_IGNORE_PODS_DEPRECATION: "1"
3061
+ }
3062
+ });
1714
3063
  }
1715
3064
  }
1716
- var transformPath = function(filePath) {
3065
+ var transformPath = function transformPath2(filePath) {
1717
3066
  return filePath.replace("_BUCK", "BUCK").replace("_gitignore", ".gitignore").replace("_gitattributes", ".gitattributes").replace("_babelrc", ".babelrc").replace("_editorconfig", ".editorconfig").replace("_eslintrc.js", ".eslintrc.js").replace("_flowconfig", ".flowconfig").replace("_buckconfig", ".buckconfig").replace("_prettierrc.js", ".prettierrc.js").replace("_bundle", ".bundle").replace("_ruby-version", ".ruby-version").replace("_node-version", ".node-version").replace("_watchmanconfig", ".watchmanconfig").replace("_xcode.env", ".xcode.env");
1718
3067
  };
1719
3068
 
1720
- export { applyAndroidDependencyPatches, generateForPlatform, getNativeDependencyInventory, installNativeDependencies, renderPrebuildFile, renderSceneDelegateSwift, validatePrebuildApp };
3069
+ export { applyAndroidDependencyPatches, enableAppComposeIntegration, generateForPlatform, generateKotlinSources, getNativeDependencyInventory, installNativeDependencies, renderIosAppIntentsSwift, renderPrebuildFile, renderSceneDelegateSwift, validatePrebuildApp };
1721
3070
  //# sourceMappingURL=prebuildWithoutExpo.native.js.map