vxrn 2.0.0-beta.98.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +1133 -182
  44. package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
  45. package/dist/exports/prebuildWithoutExpo.native.js +1606 -244
  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 +1623 -46
  148. package/src/exports/prebuildWithoutExpo.ts +1606 -216
  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,19 +1783,25 @@ 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);
1137
1797
  var stylesV31 = path.join(mainRes, "values-v31");
1138
1798
  FSExtra.mkdirSync(stylesV31, { recursive: true });
1139
- FSExtra.writeFileSync(path.join(stylesV31, "styles.xml"), `<?xml version="1.0" encoding="utf-8"?>
1140
- <resources>
1141
- <style name="AppTheme">
1142
- <item name="android:windowSplashScreenBackground">@color/splash_background</item>
1799
+ if (!styles.includes("</style>")) {
1800
+ throw new Error("[vxrn] prebuild template styles.xml lost its AppTheme </style> anchor");
1801
+ }
1802
+ FSExtra.writeFileSync(path.join(stylesV31, "styles.xml"), styles.replace("</style>", ` <item name="android:windowSplashScreenBackground">@color/splash_background</item>
1143
1803
  <item name="android:windowSplashScreenAnimatedIcon">@drawable/splash</item>
1144
- </style>
1145
- </resources>
1146
- `);
1804
+ </style>`));
1147
1805
  }
1148
1806
  function renderPrebuildFile(args) {
1149
1807
  var { relativePath, content, platform, app, nitroWebImage } = args;
@@ -1157,7 +1815,7 @@ function renderPrebuildFile(args) {
1157
1815
  destRelativePath = destRelativePath.replace(/HelloWorld/g, appName).replace(/helloworld/g, appName.toLowerCase());
1158
1816
  var rendered = content;
1159
1817
  if (rendered !== null) {
1160
- 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;
1161
1819
  var replacements = [];
1162
1820
  if (platform === "ios" && app.ios) {
1163
1821
  replacements.push([IOS_BUNDLE_PLACEHOLDER, app.ios.bundleId]);
@@ -1187,7 +1845,8 @@ function renderPrebuildFile(args) {
1187
1845
  }
1188
1846
  }
1189
1847
  if (platform === "ios" && relativePath.endsWith("/Info.plist")) {
1190
- var _app_ios1, _app_ios2, _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;
1191
1850
  var stamps = [];
1192
1851
  if (schemes.length) {
1193
1852
  stamps.push(` <key>CFBundleURLTypes</key>
@@ -1204,23 +1863,129 @@ ${schemes.map(function(scheme) {
1204
1863
  </dict>
1205
1864
  </array>`);
1206
1865
  }
1207
- 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) {
1208
1867
  stamps.push(` <key>ITSAppUsesNonExemptEncryption</key>
1209
1868
  <${app.ios.usesNonExemptEncryption ? "true" : "false"}/>`);
1210
1869
  }
1211
- 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) {
1212
1874
  stamps.push(` <key>UIFileSharingEnabled</key>
1213
1875
  <true/>
1214
1876
  <key>LSSupportsOpeningDocumentsInPlace</key>
1215
1877
  <true/>`);
1216
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
+ }
1217
1882
  if (app.notifications !== void 0) {
1218
- stamps.push(` <key>OneNativeNotificationsEnabled</key>
1883
+ stamps.push(` <key>${notificationsHost.enabledInfoPlistKey}</key>
1219
1884
  <true/>`);
1220
1885
  }
1221
- if ((_app_ios3 = app.ios) === null || _app_ios3 === void 0 ? void 0 : _app_ios3.widgets) {
1886
+ if (((_app_notifications2 = app.notifications) === null || _app_notifications2 === void 0 ? void 0 : _app_notifications2.push) === true) {
1887
+ stamps.push(` <key>${notificationsHost.pushInfoPlistKey}</key>
1888
+ <true/>`);
1889
+ }
1890
+ if ((_app_ios6 = app.ios) === null || _app_ios6 === void 0 ? void 0 : _app_ios6.widgets) {
1222
1891
  stamps.push(" <key>NSSupportsLiveActivities</key>\n <true/>");
1223
1892
  }
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
+ }
1988
+ }
1224
1989
  if (stamps.length) {
1225
1990
  var anchor = " <key>LSRequiresIPhoneOS</key>";
1226
1991
  if (!rendered.includes(anchor)) throw new Error(`[vxrn] prebuild template ${relativePath} lost its LSRequiresIPhoneOS anchor`);
@@ -1228,50 +1993,178 @@ ${schemes.map(function(scheme) {
1228
1993
  ${anchor}`);
1229
1994
  }
1230
1995
  }
1231
- 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;
1232
1998
  var anchor1 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1233
1999
  if (!rendered.includes(anchor1)) {
1234
- 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>");
1235
2008
  }
1236
2009
  rendered = rendered.replace(anchor1, `${anchor1}
1237
- <uses-permission android:name="android.permission.CAMERA" />`);
2010
+ ${stamps1.join("\n")}`);
1238
2011
  }
1239
- 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) {
1240
2013
  var anchor2 = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1241
2014
  if (!rendered.includes(anchor2)) {
1242
- 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\" />");
1243
2020
  }
1244
2021
  rendered = rendered.replace(anchor2, `${anchor2}
1245
- <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
1246
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />`);
1247
- 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])) {
1248
2041
  throw new Error("[vxrn] failed to stamp notification permissions into app manifest");
1249
2042
  }
1250
- 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>");
1251
- 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)) {
1252
2051
  throw new Error("[vxrn] failed to stamp the notification receiver into app manifest");
1253
2052
  }
1254
2053
  }
1255
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) {
1256
- var anchor3 = "dev.onejs.onenative.OneNativeNotificationsReceiver";
1257
- if (!rendered.includes(anchor3)) {
2055
+ var anchor5 = notificationsHost.receiver;
2056
+ if (!rendered.includes(anchor5)) {
1258
2057
  throw new Error("[vxrn] cannot stamp the push service: expected the notification receiver in app/src/main/AndroidManifest.xml");
1259
2058
  }
1260
- 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>");
1261
- 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)) {
1262
2067
  throw new Error("[vxrn] failed to stamp the push service into app manifest");
1263
2068
  }
1264
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
+ }
1265
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) {
1266
- var anchor4 = " </application>";
1267
- if (!rendered.includes(anchor4)) {
2159
+ var anchor8 = " </application>";
2160
+ if (!rendered.includes(anchor8)) {
1268
2161
  throw new Error("[vxrn] cannot stamp the maps api key: expected </application> in app/src/main/AndroidManifest.xml");
1269
2162
  }
1270
- rendered = rendered.replace(anchor4, ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(app.android.googleMapsApiKey)}" />
1271
- ${anchor4}`);
2163
+ rendered = rendered.replace(anchor8, ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(app.android.googleMapsApiKey)}" />
2164
+ ${anchor8}`);
1272
2165
  }
1273
2166
  if (platform === "android" && relativePath === "gradle.properties" && ((_app_notifications1 = app.notifications) === null || _app_notifications1 === void 0 ? void 0 : _app_notifications1.push) === true) {
1274
- var line = "oneNativePush=true";
2167
+ var line = `${notificationsHost.pushGradleProperty}=true`;
1275
2168
  if (!rendered.includes(line)) {
1276
2169
  var trailed = rendered.endsWith("\n") ? rendered : `${rendered}
1277
2170
  `;
@@ -1292,6 +2185,62 @@ ${line1}
1292
2185
  `;
1293
2186
  }
1294
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
+ }
2236
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.pictureInPicture) {
2237
+ var anchor11 = "android:name=\".MainActivity\"";
2238
+ if (!rendered.includes(anchor11)) {
2239
+ throw new Error("[vxrn] cannot stamp picture in picture: expected .MainActivity in app/src/main/AndroidManifest.xml");
2240
+ }
2241
+ rendered = rendered.replace(anchor11, `${anchor11}
2242
+ android:supportsPictureInPicture="true"`);
2243
+ }
1295
2244
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && schemes.length) {
1296
2245
  rendered = rendered.replace(" </activity>", ` <intent-filter>
1297
2246
  <action android:name="android.intent.action.VIEW" />
@@ -1304,35 +2253,136 @@ ${schemes.map(function(scheme) {
1304
2253
  </activity>`);
1305
2254
  }
1306
2255
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1307
- var _app_ios4;
1308
- 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"}";`);
1309
2258
  }
1310
2259
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1311
- var _app_ios5;
2260
+ var _app_ios13;
1312
2261
  if (app.version !== void 0) {
1313
2262
  rendered = rendered.replace(/MARKETING_VERSION = [^;]+;/g, `MARKETING_VERSION = "${app.version}";`);
1314
2263
  }
1315
- 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) {
1316
2265
  rendered = rendered.replace(/CURRENT_PROJECT_VERSION = [^;]+;/g, `CURRENT_PROJECT_VERSION = ${app.ios.buildNumber};`);
1317
2266
  }
1318
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
+ }
1319
2277
  if (platform === "ios" && relativePath.endsWith("/Info.plist")) {
1320
- var _app_imagePicker1;
1321
- if (((_app_imagePicker1 = app.imagePicker) === null || _app_imagePicker1 === void 0 ? void 0 : _app_imagePicker1.camera) !== void 0) {
1322
- var anchor5 = " <key>LSRequiresIPhoneOS</key>";
1323
- if (!rendered.includes(anchor5)) {
1324
- 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);
1325
2292
  }
1326
- rendered = rendered.replace(anchor5, ` <key>NSCameraUsageDescription</key>
1327
- <string>${escapeXml(app.imagePicker.camera)}</string>
1328
- ${anchor5}`);
1329
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
+ }
2351
+ }
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, "");
1330
2366
  rendered = patchIosInfoPlistSceneManifest(rendered);
1331
2367
  }
1332
2368
  if (platform === "ios" && relativePath.endsWith("/AppDelegate.swift")) {
1333
- 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
+ }
1334
2384
  }
1335
- 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)) {
1336
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};`);
1337
2387
  if (relativePath === "Podfile") {
1338
2388
  rendered = rendered.replace(" )\n end\nend", ` )
@@ -1347,44 +2397,58 @@ end`);
1347
2397
  }
1348
2398
  }
1349
2399
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1350
- var _app_notifications2, _app_ios6, _app_ios7;
1351
- 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);
1352
2402
  rendered = patchIosPbxprojSceneDelegate(rendered, appName);
1353
- if (((_app_notifications2 = app.notifications) === null || _app_notifications2 === void 0 ? void 0 : _app_notifications2.push) === true && !((_app_ios6 = app.ios) === null || _app_ios6 === void 0 ? void 0 : _app_ios6.widgets)) {
1354
- 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));
1355
2411
  }
1356
- if ((_app_ios7 = app.ios) === null || _app_ios7 === void 0 ? void 0 : _app_ios7.widgets) rendered = patchIosPbxprojWidgets(rendered, app);
1357
2412
  }
1358
2413
  if (platform === "ios" && relativePath === "Podfile") {
1359
- var _app_ios8, _app_ios9, _app_ios10;
1360
- 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'
1361
2416
  ${rendered}`;
1362
- 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) {
1363
2418
  rendered = rendered.replace(/^(platform :ios, .+)$/m, `$1
1364
2419
  use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1365
2420
  }
1366
- 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) {
1367
2422
  rendered = nativeProjectPatches.injectReactNativeScreensGammaIntoPodfile(rendered);
1368
2423
  }
1369
2424
  rendered = nativeProjectPatches.injectFmtCxx17FixIntoPodfile(rendered);
2425
+ rendered = nativeProjectPatches.injectWebGPUHeaderPathsIntoPodfile(rendered);
1370
2426
  rendered = nativeProjectPatches.injectOneSwiftPackagesIntoPodfile(rendered);
1371
2427
  if (nitroWebImage) rendered = nativeProjectPatches.injectNitroWebImageModularHeaderIntoPodfile(rendered);
1372
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()"])`);
1373
2434
  if (!rendered.includes("[vxrn/one] fmt c++17 fix") || !rendered.includes("[vxrn/one] minify iOS Hermes Release bundle input")) {
1374
2435
  throw new Error("[vxrn] failed to apply required iOS Podfile patches");
1375
2436
  }
1376
2437
  }
1377
2438
  if (platform === "android" && relativePath === "app/build.gradle") {
1378
- var _app_android3;
2439
+ var _app_android11;
1379
2440
  rendered = nativeProjectPatches.replaceAppBuildGradleReactBlock(rendered);
1380
2441
  rendered = nativeProjectPatches.addDepsPatchToAppBuildGradle(rendered);
1381
2442
  if (!rendered.includes("entryFile = file(\"../../package.json\")") || !rendered.includes("[vxrn/one] ensure patches are applied")) {
1382
2443
  throw new Error("[vxrn] failed to apply required Android Gradle patches");
1383
2444
  }
2445
+ if (app.updates !== void 0) {
2446
+ rendered = patchAndroidBuildGradleUpdatesManifest(rendered, app.updates.runtimeVersion);
2447
+ }
1384
2448
  if (app.version !== void 0) {
1385
2449
  rendered = rendered.replace(/versionName "[^"]*"/g, `versionName "${app.version}"`);
1386
2450
  }
1387
- 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) {
1388
2452
  rendered = rendered.replace(/versionCode \d+/g, `versionCode ${app.android.versionCode}`);
1389
2453
  }
1390
2454
  }
@@ -1394,9 +2458,76 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1394
2458
  throw new Error("[vxrn] expected two React Native Gradle plugin paths");
1395
2459
  }
1396
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"])`);
2466
+ }
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
+ }
1397
2514
  }
1398
- if (platform === "android" && ((_app_android2 = app.android) === null || _app_android2 === void 0 ? void 0 : _app_android2.minSdk) !== void 0) {
1399
- rendered = rendered.replace(/minSdkVersion = \d+/g, `minSdkVersion = ${app.android.minSdk}`);
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}`);
1400
2531
  }
1401
2532
  }
1402
2533
  return {
@@ -1404,14 +2535,14 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1404
2535
  content: rendered
1405
2536
  };
1406
2537
  }
1407
- var generateForPlatform = async function(root, platform, app) {
2538
+ var generateForPlatform = async function generateForPlatform2(root, platform, app) {
1408
2539
  var outDir = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : path.resolve(root, platform);
1409
2540
  var _ref, _ref1;
1410
2541
  var _walkModule_default;
1411
2542
  validatePrebuildApp(app, platform);
1412
2543
  var dest = outDir;
1413
2544
  var require2 = module.createRequire(root + "/");
1414
- 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");
1415
2546
  var src = path.join(path.dirname(require2.resolve("@react-native-community/template/template/package.json", { paths: [root] })), platform);
1416
2547
  var walkModule = await import(pathToFileURL(importPath).href);
1417
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;
@@ -1473,48 +2604,210 @@ var generateForPlatform = async function(root, platform, app) {
1473
2604
  platform,
1474
2605
  app
1475
2606
  });
2607
+ if (platform === "android") await generateAdaptiveIcon({
2608
+ root,
2609
+ dest,
2610
+ app
2611
+ });
1476
2612
  await generateSplashScreen({
1477
2613
  root,
1478
2614
  dest,
1479
2615
  platform,
1480
2616
  app
1481
2617
  });
2618
+ if (platform === "ios") generateAccentColor({
2619
+ dest,
2620
+ app
2621
+ });
2622
+ copyAppResources({
2623
+ root,
2624
+ dest,
2625
+ platform,
2626
+ app
2627
+ });
1482
2628
  generateSceneDelegate({
1483
2629
  dest,
1484
2630
  platform,
1485
2631
  app
1486
2632
  });
2633
+ generateIosAppIntents(dest, platform, app);
2634
+ if (platform === "ios") generateOneBridgingHeader(dest, app);
1487
2635
  if (platform === "ios") generateIosWidgets(dest, app);
1488
- if (platform === "ios") generateSwiftPackages({
2636
+ if (platform === "ios") await generateSwiftPackages({
2637
+ root,
2638
+ dest
2639
+ });
2640
+ if (platform === "android") await generateKotlinSources({
1489
2641
  root,
1490
2642
  dest
1491
2643
  });
1492
2644
  };
1493
- 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) {
1494
2770
  var { root, dest } = param;
2771
+ var _ref;
2772
+ var _manifest_workspaces;
1495
2773
  var skip = /* @__PURE__ */ new Set([
1496
2774
  "node_modules",
1497
2775
  "ios",
1498
2776
  "android",
1499
2777
  "dist",
1500
2778
  "types",
1501
- "build"
2779
+ "build",
2780
+ "tests",
2781
+ "__tests__",
2782
+ "scripts",
2783
+ "evidence"
1502
2784
  ]);
1503
- var packageDirs = [];
1504
- var walk = function(dir) {
1505
- var entries = FSExtra.readdirSync(dir, { withFileTypes: true });
1506
- if (entries.some(function(entry2) {
1507
- return entry2.isFile() && entry2.name === "Package.swift";
1508
- })) {
1509
- packageDirs.push(dir);
1510
- return;
1511
- }
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;
1512
2803
  var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1513
2804
  try {
1514
- 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) {
1515
2806
  var entry = _step2.value;
1516
- if (!entry.isDirectory() || entry.name.startsWith(".") || skip.has(entry.name)) continue;
1517
- 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);
1518
2811
  }
1519
2812
  } catch (err) {
1520
2813
  _didIteratorError2 = true;
@@ -1531,15 +2824,65 @@ function generateSwiftPackages(param) {
1531
2824
  }
1532
2825
  }
1533
2826
  };
1534
- 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");
1535
2878
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
1536
2879
  try {
1537
2880
  var _loop = function() {
1538
- var packageDir = _step.value;
1539
- var id = swiftPackageId(packageDir);
2881
+ var [id, packageDir] = _step.value;
1540
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"));
1541
2884
  var sources = [];
1542
- var collect = function(dir) {
2885
+ var collect = function collect1(dir) {
1543
2886
  var _iteratorNormalCompletion3 = true, _didIteratorError3 = false, _iteratorError3 = void 0;
1544
2887
  try {
1545
2888
  for (var _iterator3 = FSExtra.readdirSync(dir, { withFileTypes: true })[Symbol.iterator](), _step2; !(_iteratorNormalCompletion3 = (_step2 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
@@ -1565,6 +2908,16 @@ function generateSwiftPackages(param) {
1565
2908
  }
1566
2909
  };
1567
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
+ }
1568
2921
  var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
1569
2922
  try {
1570
2923
  for (var _iterator2 = sources[Symbol.iterator](), _step1; !(_iteratorNormalCompletion2 = (_step1 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
@@ -1587,6 +2940,9 @@ function generateSwiftPackages(param) {
1587
2940
  }
1588
2941
  }
1589
2942
  }
2943
+ if (artifacts.glue) {
2944
+ FSExtra.writeFileSync(path.join(podDir, "Sources", "OneNativeSource.generated.swift"), artifacts.glue);
2945
+ }
1590
2946
  FSExtra.writeFileSync(path.join(podDir, `${id}.podspec`), `Pod::Spec.new do |s|
1591
2947
  s.name = '${id}'
1592
2948
  s.version = '0.0.0'
@@ -1595,15 +2951,15 @@ function generateSwiftPackages(param) {
1595
2951
  s.license = 'MIT'
1596
2952
  s.author = 'one'
1597
2953
  s.source = { :path => '.' }
1598
- s.swift_version = '6.0'
2954
+ s.swift_version = '${manifest.languageMode}.0'
1599
2955
  s.source_files = 'Sources/**/*.swift', 'Register.m'
1600
- s.dependency 'VxrnNative'
2956
+ s.dependency 'One'
1601
2957
  s.pod_target_xcconfig = {
1602
- 'OTHER_SWIFT_FLAGS' => '$(inherited) -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` : ""}',
1603
2959
  }
1604
2960
  end
1605
2961
  `);
1606
- FSExtra.writeFileSync(path.join(podDir, "Register.m"), `#import <Foundation/Foundation.h>
2962
+ FSExtra.writeFileSync(path.join(podDir, "Register.m"), hasView ? `#import <Foundation/Foundation.h>
1607
2963
 
1608
2964
  extern int ${id}_main(int argc, char **argv);
1609
2965
  extern void OneSwiftRegisterPackage(const char *name, int (*entry)(int, char **));
@@ -1616,9 +2972,9 @@ extern void OneSwiftRegisterPackage(const char *name, int (*entry)(int, char **)
1616
2972
  OneSwiftRegisterPackage("${id}", ${id}_main);
1617
2973
  }
1618
2974
  @end
1619
- `);
2975
+ ` : "#import <Foundation/Foundation.h>\n");
1620
2976
  };
1621
- 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();
1622
2978
  } catch (err) {
1623
2979
  _didIteratorError = true;
1624
2980
  _iteratorError = err;
@@ -1642,15 +2998,14 @@ function applyAndroidDependencyPatches(args) {
1642
2998
  return;
1643
2999
  }
1644
3000
  var activityPath = path.join(root, "android", "app", "src", "main", "java", ...app.android.applicationId.split("."), "MainActivity.kt");
1645
- var rendered = nativeProjectPatches.addReactNativeScreensFix(FSExtra.readFileSync(activityPath, "utf8"));
3001
+ var rendered = nativeProjectPatches.holdLaunchScreenInMainActivity(nativeProjectPatches.addReactNativeScreensFix(FSExtra.readFileSync(activityPath, "utf8")));
1646
3002
  if (!rendered.includes("RNScreensFragmentFactory")) {
1647
3003
  throw new Error("[vxrn] failed to apply the react-native-screens activity patch");
1648
3004
  }
1649
3005
  FSExtra.writeFileSync(activityPath, rendered);
1650
3006
  }
1651
3007
  async function getNativeDependencyInventory(root) {
1652
- var require2 = module.createRequire(root + "/");
1653
- var cliConfigPath = require2.resolve("@react-native-community/cli-config", { paths: [root] });
3008
+ var cliConfigPath = requireVxrn.resolve("@react-native-community/cli-config");
1654
3009
  var cliConfig = await import(pathToFileURL(cliConfigPath).href);
1655
3010
  var config = await cliConfig.loadConfigAsync({ projectRoot: root });
1656
3011
  var inventory = [];
@@ -1697,12 +3052,19 @@ async function getNativeDependencyInventory(root) {
1697
3052
  function installNativeDependencies(args) {
1698
3053
  var { root, platform } = args;
1699
3054
  if (!platform || platform === "ios") {
1700
- 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
+ });
1701
3063
  }
1702
3064
  }
1703
- var transformPath = function(filePath) {
3065
+ var transformPath = function transformPath2(filePath) {
1704
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");
1705
3067
  };
1706
3068
 
1707
- export { applyAndroidDependencyPatches, generateForPlatform, getNativeDependencyInventory, installNativeDependencies, renderPrebuildFile, renderSceneDelegateSwift, validatePrebuildApp };
3069
+ export { applyAndroidDependencyPatches, enableAppComposeIntegration, generateForPlatform, generateKotlinSources, getNativeDependencyInventory, installNativeDependencies, renderIosAppIntentsSwift, renderPrebuildFile, renderSceneDelegateSwift, validatePrebuildApp };
1708
3070
  //# sourceMappingURL=prebuildWithoutExpo.native.js.map