bleam 0.0.7 → 0.0.9

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 (92) hide show
  1. package/dist/cli.cjs +23 -4
  2. package/dist/cli.d.cts +2 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +23 -4
  5. package/dist/{ui-234Plg7Z.d.cts → ui-Bg11tvlc.d.ts} +7 -7
  6. package/dist/ui.d.ts +1 -1
  7. package/dist/window.d.ts +1 -1
  8. package/package.json +4 -1
  9. package/templates/image-generation/app/index.tsx +1 -1
  10. package/templates/native/.gitattributes +1 -0
  11. package/templates/native/App.tsx +26 -0
  12. package/templates/native/app.json +12 -0
  13. package/templates/native/index.ts +8 -0
  14. package/templates/native/ios/.xcode.env +11 -0
  15. package/templates/native/ios/Bleam/AI/Flux2/Configuration/Flux2Config.swift +288 -0
  16. package/templates/native/ios/Bleam/AI/Flux2/Configuration/MemoryConfig.swift +233 -0
  17. package/templates/native/ios/Bleam/AI/Flux2/Configuration/MemoryOptimizationConfig.swift +157 -0
  18. package/templates/native/ios/Bleam/AI/Flux2/Configuration/ModelRegistry.swift +425 -0
  19. package/templates/native/ios/Bleam/AI/Flux2/Configuration/QuantizationConfig.swift +138 -0
  20. package/templates/native/ios/Bleam/AI/Flux2/Configuration/TransformerRepoProfile.swift +59 -0
  21. package/templates/native/ios/Bleam/AI/Flux2/Configuration/VAEConfig.swift +134 -0
  22. package/templates/native/ios/Bleam/AI/Flux2/Flux2Core.swift +55 -0
  23. package/templates/native/ios/Bleam/AI/Flux2/Loading/WeightLoader.swift +1192 -0
  24. package/templates/native/ios/Bleam/AI/Flux2/Pipeline/FluxImageRunner.swift +1282 -0
  25. package/templates/native/ios/Bleam/AI/Flux2/Pipeline/LatentUtils.swift +191 -0
  26. package/templates/native/ios/Bleam/AI/Flux2/Scheduler/FlowMatchEulerScheduler.swift +279 -0
  27. package/templates/native/ios/Bleam/AI/Flux2/Text/KleinTextEncoder.swift +380 -0
  28. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2Attention.swift +379 -0
  29. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2Embeddings.swift +159 -0
  30. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2FeedForward.swift +154 -0
  31. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2FusedKernels.swift +198 -0
  32. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2KVCache.swift +36 -0
  33. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2Modulation.swift +193 -0
  34. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2ParallelAttention.swift +389 -0
  35. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2RoPE.swift +304 -0
  36. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2SingleBlock.swift +290 -0
  37. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2Transformer.swift +530 -0
  38. package/templates/native/ios/Bleam/AI/Flux2/Transformer/Flux2TransformerBlock.swift +362 -0
  39. package/templates/native/ios/Bleam/AI/Flux2/Utils/Flux2Debug.swift +101 -0
  40. package/templates/native/ios/Bleam/AI/Flux2/Utils/MLXCheckpoint.swift +118 -0
  41. package/templates/native/ios/Bleam/AI/Flux2/Utils/MemoryManager.swift +201 -0
  42. package/templates/native/ios/Bleam/AI/Flux2/VAE/AutoencoderKL.swift +476 -0
  43. package/templates/native/ios/Bleam/AI/Flux2/VAE/ResnetBlock.swift +316 -0
  44. package/templates/native/ios/Bleam/AI/Flux2/VAE/VAEDecoder.swift +120 -0
  45. package/templates/native/ios/Bleam/AI/Flux2/VAE/VAEEncoder.swift +136 -0
  46. package/templates/native/ios/Bleam/AppDelegate.swift +373 -0
  47. package/templates/native/ios/Bleam/Appearance.swift +62 -0
  48. package/templates/native/ios/Bleam/Bridging-Header.h +3 -0
  49. package/templates/native/ios/Bleam/Images.xcassets/AppIcon.appiconset/Contents.json +13 -0
  50. package/templates/native/ios/Bleam/Images.xcassets/Contents.json +6 -0
  51. package/templates/native/ios/Bleam/Info.plist +76 -0
  52. package/templates/native/ios/Bleam/PrivacyInfo.xcprivacy +48 -0
  53. package/templates/native/ios/Bleam/SceneDelegate.swift +58 -0
  54. package/templates/native/ios/Bleam/SplashScreen.storyboard +47 -0
  55. package/templates/native/ios/Bleam/Supporting/Expo.plist +6 -0
  56. package/templates/native/ios/Bleam/bleam.entitlements +10 -0
  57. package/templates/native/ios/Bleam.xcodeproj/project.pbxproj +1146 -0
  58. package/templates/native/ios/Bleam.xcodeproj/xcshareddata/xcschemes/Bleam.xcscheme +88 -0
  59. package/templates/native/ios/GenerationService/GenerationService.entitlements +10 -0
  60. package/templates/native/ios/GenerationService/ImageGenerationRunner.swift +591 -0
  61. package/templates/native/ios/GenerationService/Info.plist +31 -0
  62. package/templates/native/ios/GenerationService/main.swift +165 -0
  63. package/templates/native/ios/PlatformHelper/Info.plist +29 -0
  64. package/templates/native/ios/PlatformHelper/main.swift +335 -0
  65. package/templates/native/ios/Podfile +198 -0
  66. package/templates/native/ios/Podfile.lock +2284 -0
  67. package/templates/native/ios/Podfile.properties.json +5 -0
  68. package/templates/native/ios/Shared/Generation/GenerationServiceProtocol.swift +12 -0
  69. package/templates/native/ios/Shared/Generation/GenerationWorkerProtocol.swift +124 -0
  70. package/templates/native/metro.config.js +6 -0
  71. package/templates/native/modules/bleam-runtime/BleamRuntime.podspec +14 -0
  72. package/templates/native/modules/bleam-runtime/expo-module.config.json +8 -0
  73. package/templates/native/modules/bleam-runtime/ios/AIModule.swift +1258 -0
  74. package/templates/native/modules/bleam-runtime/ios/GenerationContracts.swift +135 -0
  75. package/templates/native/modules/bleam-runtime/ios/PlatformModule.swift +313 -0
  76. package/templates/native/modules/bleam-runtime/package.json +5 -0
  77. package/templates/native/package.json +39 -0
  78. package/templates/native/scripts/build/mlx-frameworks.ts +421 -0
  79. package/templates/native/scripts/start/index.ts +474 -0
  80. package/templates/native/scripts/start/known-failures.ts +20 -0
  81. package/templates/native/scripts/start/loader.ts +76 -0
  82. package/templates/native/scripts/start/native-state.ts +242 -0
  83. package/templates/native/scripts/start/package.json +4 -0
  84. package/templates/native/scripts/start/swift-packages.ts +414 -0
  85. package/templates/native/scripts/start/xcode-formatter.ts +106 -0
  86. package/templates/native/tsconfig.json +14 -0
  87. package/templates/native/yarn.lock +3749 -0
  88. package/dist/ui-BJmXhz9Q.d.ts +0 -92
  89. package/dist/ui-Dd7SXdbg.d.cts +0 -92
  90. package/dist/ui-Ds88eETu.d.ts +0 -92
  91. package/dist/ui-TaqnB5SP.d.ts +0 -92
  92. package/dist/ui-WQvnXL0W.d.ts +0 -92
@@ -0,0 +1,373 @@
1
+ internal import Expo
2
+ import React
3
+ import ReactAppDependencyProvider
4
+ import UIKit
5
+ import CryptoKit
6
+ import Darwin
7
+
8
+ func launchArgument(_ name: String) -> String? {
9
+ let arguments = ProcessInfo.processInfo.arguments
10
+ guard let flagIndex = arguments.firstIndex(of: name) else {
11
+ return nil
12
+ }
13
+
14
+ let valueIndex = arguments.index(after: flagIndex)
15
+ guard arguments.indices.contains(valueIndex) else {
16
+ return nil
17
+ }
18
+
19
+ return arguments[valueIndex]
20
+ }
21
+
22
+ @main
23
+ class AppDelegate: ExpoAppDelegate {
24
+ public override func application(
25
+ _ application: UIApplication,
26
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
27
+ ) -> Bool {
28
+ let launched = super.application(application, didFinishLaunchingWithOptions: launchOptions)
29
+ if launched {
30
+ PlatformHelperInstaller.refreshIfInstalledApp()
31
+ }
32
+ return launched
33
+ }
34
+
35
+ public func application(
36
+ _ application: UIApplication,
37
+ configurationForConnecting connectingSceneSession: UISceneSession,
38
+ options: UIScene.ConnectionOptions
39
+ ) -> UISceneConfiguration {
40
+ let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
41
+ configuration.delegateClass = SceneDelegate.self
42
+ return configuration
43
+ }
44
+
45
+ // Linking API
46
+ public override func application(
47
+ _ app: UIApplication,
48
+ open url: URL,
49
+ options: [UIApplication.OpenURLOptionsKey: Any] = [:]
50
+ ) -> Bool {
51
+ return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
52
+ }
53
+
54
+ // Universal Links
55
+ public override func application(
56
+ _ application: UIApplication,
57
+ continue userActivity: NSUserActivity,
58
+ restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
59
+ ) -> Bool {
60
+ let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
61
+ return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
62
+ }
63
+ }
64
+
65
+ private enum PlatformHelperInstaller {
66
+ static func refreshIfInstalledApp() {
67
+ #if targetEnvironment(macCatalyst)
68
+ let homeDirectory = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
69
+ let homeApplications = homeDirectory
70
+ .appendingPathComponent("Applications", isDirectory: true)
71
+ .standardizedFileURL.path + "/"
72
+ guard Bundle.main.bundleURL.standardizedFileURL.path.hasPrefix(homeApplications) else {
73
+ return
74
+ }
75
+ guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return }
76
+
77
+ let serviceName = "PlatformHelper"
78
+ let bundledService = Bundle.main.bundleURL
79
+ .appendingPathComponent("Contents/XPCServices/\(serviceName).xpc", isDirectory: true)
80
+ guard FileManager.default.fileExists(atPath: bundledService.path) else {
81
+ NSLog("Bleam helper unavailable: bundled executable is missing")
82
+ return
83
+ }
84
+
85
+ let label = "\(bundleIdentifier).PlatformHelper"
86
+ let domain = "gui/\(getuid())"
87
+ _ = runLaunchctl(["bootout", "\(domain)/\(label)"])
88
+
89
+ let helperRoot = homeDirectory
90
+ .appendingPathComponent("Library/Application Support/Bleam/Helpers", isDirectory: true)
91
+ .appendingPathComponent(bundleIdentifier, isDirectory: true)
92
+ let installedService = helperRoot.appendingPathComponent("\(serviceName).xpc", isDirectory: true)
93
+ let executable = installedService
94
+ .appendingPathComponent("Contents/MacOS/\(serviceName)")
95
+ let launchAgents = homeDirectory
96
+ .appendingPathComponent("Library/LaunchAgents", isDirectory: true)
97
+ let plistURL = launchAgents.appendingPathComponent("\(label).plist")
98
+ let propertyList: [String: Any] = [
99
+ "Label": label,
100
+ "ProgramArguments": [executable.path],
101
+ "RunAtLoad": true,
102
+ "KeepAlive": true,
103
+ "ProcessType": "Background",
104
+ "MachServices": ["\(bundleIdentifier).PlatformHelper": true],
105
+ "EnvironmentVariables": ["XPC_SERVICE_NAME": "\(bundleIdentifier).PlatformHelper"],
106
+ ]
107
+
108
+ do {
109
+ try FileManager.default.createDirectory(
110
+ at: helperRoot,
111
+ withIntermediateDirectories: true
112
+ )
113
+ try? FileManager.default.removeItem(at: installedService)
114
+ try FileManager.default.copyItem(at: bundledService, to: installedService)
115
+ try FileManager.default.createDirectory(
116
+ at: launchAgents,
117
+ withIntermediateDirectories: true
118
+ )
119
+ let data = try PropertyListSerialization.data(
120
+ fromPropertyList: propertyList,
121
+ format: .xml,
122
+ options: 0
123
+ )
124
+ try data.write(to: plistURL, options: .atomic)
125
+ } catch {
126
+ NSLog("Bleam helper install failed: %@", error.localizedDescription)
127
+ return
128
+ }
129
+
130
+ if runLaunchctl(["bootstrap", domain, plistURL.path]) != 0 {
131
+ NSLog("Bleam helper registration failed")
132
+ }
133
+ #endif
134
+ }
135
+
136
+ private static func runLaunchctl(_ arguments: [String]) -> Int32 {
137
+ let values = ["launchctl"] + arguments
138
+ var argv = values.map { strdup($0) }
139
+ argv.append(nil)
140
+ defer { argv.compactMap { $0 }.forEach { free($0) } }
141
+
142
+ var pid: pid_t = 0
143
+ let result = posix_spawn(&pid, "/bin/launchctl", nil, nil, &argv, environ)
144
+ guard result == 0 else { return Int32(result) }
145
+ var status: Int32 = 0
146
+ guard waitpid(pid, &status, 0) == pid else { return -1 }
147
+ return status
148
+ }
149
+ }
150
+
151
+ class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
152
+ private let bundleOverrideURL: URL?
153
+
154
+ init(bundleURL: URL? = nil) {
155
+ bundleOverrideURL = bundleURL
156
+ super.init()
157
+ }
158
+
159
+ // Extension point for config-plugins
160
+
161
+ override func sourceURL(for bridge: RCTBridge) -> URL? {
162
+ // needed to return the correct URL for expo-dev-client.
163
+ bridge.bundleURL ?? bundleURL()
164
+ }
165
+
166
+ override func customize(_ rootView: UIView) {
167
+ super.customize(rootView)
168
+ applyRootAppearance(to: rootView)
169
+ }
170
+
171
+ override func bundleURL() -> URL? {
172
+ if let bundleOverrideURL {
173
+ return bundleOverrideURL
174
+ }
175
+
176
+ if let bundleURL = launchArgument("--bleam-bundle-url") {
177
+ return URL(string: bundleURL)
178
+ }
179
+
180
+ #if DEBUG
181
+ return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
182
+ #else
183
+ return OTAUpdateManager.shared.launchBundleURL()
184
+ #endif
185
+ }
186
+ }
187
+
188
+ private struct OTAArtifact: Decodable {
189
+ let url: URL
190
+ let sizeBytes: Int
191
+ let sha256: String
192
+ }
193
+
194
+ private struct OTARelease: Decodable {
195
+ let schemaVersion: Int
196
+ let kind: String
197
+ let releaseId: String
198
+ let bundleIdentifier: String
199
+ let teamIdentifier: String
200
+ let runtimeVersion: String
201
+ let artifact: OTAArtifact
202
+ }
203
+
204
+ final class OTAUpdateManager {
205
+ static let shared = OTAUpdateManager()
206
+
207
+ private let fileManager = FileManager.default
208
+ private let defaults = UserDefaults.standard
209
+ private let activeKey = "BleamOTAActiveRelease"
210
+ private let attemptedKey = "BleamOTAAttemptedRelease"
211
+ private let rejectedKey = "BleamOTARejectedRelease"
212
+ private var launchingRelease: String?
213
+
214
+ private var cacheRoot: URL {
215
+ let caches = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
216
+ let bundleIdentifier = Bundle.main.bundleIdentifier ?? "app"
217
+ return caches.appendingPathComponent("Bleam/OTA/\(bundleIdentifier)", isDirectory: true)
218
+ }
219
+
220
+ private init() {
221
+ for name in ["RCTJavaScriptDidLoadNotification", "RCTContentDidAppearNotification"] {
222
+ NotificationCenter.default.addObserver(
223
+ forName: NSNotification.Name(rawValue: name),
224
+ object: nil,
225
+ queue: .main
226
+ ) { [weak self] _ in
227
+ self?.markLaunchSuccessful()
228
+ }
229
+ }
230
+ }
231
+
232
+ func launchBundleURL() -> URL? {
233
+ guard let releaseId = defaults.string(forKey: activeKey) else {
234
+ return embeddedBundleURL()
235
+ }
236
+
237
+ if defaults.string(forKey: attemptedKey) == releaseId {
238
+ defaults.set(releaseId, forKey: rejectedKey)
239
+ defaults.removeObject(forKey: activeKey)
240
+ defaults.removeObject(forKey: attemptedKey)
241
+ return embeddedBundleURL()
242
+ }
243
+
244
+ let bundle = cacheRoot
245
+ .appendingPathComponent(releaseId, isDirectory: true)
246
+ .appendingPathComponent("bundle/bundle.js")
247
+ guard fileManager.fileExists(atPath: bundle.path) else {
248
+ defaults.removeObject(forKey: activeKey)
249
+ return embeddedBundleURL()
250
+ }
251
+
252
+ launchingRelease = releaseId
253
+ defaults.set(releaseId, forKey: attemptedKey)
254
+ return bundle
255
+ }
256
+
257
+ func checkForUpdate() {
258
+ guard
259
+ let baseUrlString = Bundle.main.object(forInfoDictionaryKey: "BleamUpdateServiceURL") as? String,
260
+ let baseUrl = URL(string: baseUrlString),
261
+ let bundleIdentifier = Bundle.main.bundleIdentifier,
262
+ let runtimeVersion = Bundle.main.object(forInfoDictionaryKey: "BleamRuntimeVersion") as? String
263
+ else {
264
+ NSLog("Bleam OTA disabled: missing update URL, bundle identifier, or runtime version")
265
+ return
266
+ }
267
+
268
+ let path = "/v1/apps/\(bundleIdentifier)/ota/\(runtimeVersion)"
269
+ guard let url = URL(string: path, relativeTo: baseUrl)?.absoluteURL else {
270
+ NSLog("Bleam OTA disabled: invalid resolver URL")
271
+ return
272
+ }
273
+
274
+ NSLog("Bleam OTA checking %@", url.absoluteString)
275
+ URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
276
+ if let error {
277
+ NSLog("Bleam OTA resolver failed: %@", error.localizedDescription)
278
+ }
279
+ guard
280
+ let self,
281
+ let response = response as? HTTPURLResponse,
282
+ response.statusCode == 200,
283
+ let data,
284
+ let release = try? JSONDecoder().decode(OTARelease.self, from: data)
285
+ else {
286
+ let status = (response as? HTTPURLResponse)?.statusCode ?? 0
287
+ NSLog("Bleam OTA resolver returned an unusable response: %d", status)
288
+ return
289
+ }
290
+ self.download(release)
291
+ }.resume()
292
+ }
293
+
294
+ private func download(_ release: OTARelease) {
295
+ guard
296
+ release.schemaVersion == 1,
297
+ release.kind == "ota",
298
+ release.bundleIdentifier == Bundle.main.bundleIdentifier,
299
+ release.runtimeVersion == Bundle.main.object(forInfoDictionaryKey: "BleamRuntimeVersion") as? String,
300
+ release.teamIdentifier == Bundle.main.object(forInfoDictionaryKey: "BleamTeamIdentifier") as? String,
301
+ release.releaseId != defaults.string(forKey: activeKey),
302
+ release.releaseId != defaults.string(forKey: rejectedKey)
303
+ else {
304
+ NSLog("Bleam OTA rejected release %@", release.releaseId)
305
+ return
306
+ }
307
+
308
+ NSLog("Bleam OTA downloading %@", release.releaseId)
309
+ URLSession.shared.downloadTask(with: release.artifact.url) { [weak self] temporaryUrl, _, error in
310
+ if let error {
311
+ NSLog("Bleam OTA download failed: %@", error.localizedDescription)
312
+ }
313
+ guard let self, let temporaryUrl else { return }
314
+ guard
315
+ let attributes = try? self.fileManager.attributesOfItem(atPath: temporaryUrl.path),
316
+ attributes[.size] as? Int == release.artifact.sizeBytes,
317
+ let data = try? Data(contentsOf: temporaryUrl),
318
+ SHA256.hash(data: data).map({ String(format: "%02x", $0) }).joined() == release.artifact.sha256
319
+ else {
320
+ NSLog("Bleam OTA artifact verification failed for %@", release.releaseId)
321
+ return
322
+ }
323
+
324
+ let destination = self.cacheRoot.appendingPathComponent(release.releaseId, isDirectory: true)
325
+ try? self.fileManager.removeItem(at: destination)
326
+ do {
327
+ try self.fileManager.createDirectory(at: destination, withIntermediateDirectories: true)
328
+ try self.extract(temporaryUrl, to: destination)
329
+ guard self.fileManager.fileExists(
330
+ atPath: destination.appendingPathComponent("bundle/bundle.js").path
331
+ ) else {
332
+ try? self.fileManager.removeItem(at: destination)
333
+ return
334
+ }
335
+ self.defaults.removeObject(forKey: self.attemptedKey)
336
+ self.defaults.set(release.releaseId, forKey: self.activeKey)
337
+ NSLog("Bleam OTA staged %@ for next launch", release.releaseId)
338
+ } catch {
339
+ NSLog("Bleam OTA extraction failed: %@", error.localizedDescription)
340
+ try? self.fileManager.removeItem(at: destination)
341
+ }
342
+ }.resume()
343
+ }
344
+
345
+ private func extract(_ archive: URL, to destination: URL) throws {
346
+ let arguments = ["ditto", "-x", "-k", archive.path, destination.path]
347
+ var argv = arguments.map { strdup($0) }
348
+ argv.append(nil)
349
+ defer { argv.compactMap { $0 }.forEach { free($0) } }
350
+
351
+ var pid: pid_t = 0
352
+ let spawnResult = posix_spawn(&pid, "/usr/bin/ditto", nil, nil, &argv, environ)
353
+ guard spawnResult == 0 else {
354
+ throw NSError(domain: NSPOSIXErrorDomain, code: Int(spawnResult))
355
+ }
356
+ var status: Int32 = 0
357
+ guard waitpid(pid, &status, 0) == pid, status == 0 else {
358
+ throw NSError(domain: NSPOSIXErrorDomain, code: Int(status))
359
+ }
360
+ }
361
+
362
+ private func markLaunchSuccessful() {
363
+ guard let releaseId = launchingRelease else { return }
364
+ defaults.removeObject(forKey: attemptedKey)
365
+ launchingRelease = nil
366
+ let releaseRoot = cacheRoot.appendingPathComponent(releaseId, isDirectory: true)
367
+ try? fileManager.createDirectory(at: releaseRoot, withIntermediateDirectories: true)
368
+ }
369
+
370
+ private func embeddedBundleURL() -> URL? {
371
+ Bundle.main.url(forResource: "main", withExtension: "jsbundle")
372
+ }
373
+ }
@@ -0,0 +1,62 @@
1
+ import UIKit
2
+
3
+ struct Appearance {
4
+ let windowBackgroundColor: UIColor?
5
+ let userInterfaceStyle: UIUserInterfaceStyle
6
+
7
+ static let `default` = Appearance(
8
+ windowBackgroundColor: nil,
9
+ userInterfaceStyle: .unspecified
10
+ )
11
+ }
12
+
13
+ func parseColor(from hex: String?) -> UIColor? {
14
+ guard let hex else {
15
+ return nil
16
+ }
17
+
18
+ let value = hex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "#", with: "")
19
+ guard value.count == 6, let number = Int(value, radix: 16) else {
20
+ return nil
21
+ }
22
+
23
+ return UIColor(
24
+ red: CGFloat((number >> 16) & 0xff) / 255,
25
+ green: CGFloat((number >> 8) & 0xff) / 255,
26
+ blue: CGFloat(number & 0xff) / 255,
27
+ alpha: 1
28
+ )
29
+ }
30
+
31
+ func parseAppearance(from value: Any?) -> Appearance {
32
+ guard let object = value as? [String: Any] else {
33
+ return .default
34
+ }
35
+
36
+ let window = object["window"] as? [String: Any]
37
+ let style = object["userInterfaceStyle"] as? String
38
+
39
+ return Appearance(
40
+ windowBackgroundColor: parseColor(from: window?["backgroundColor"] as? String),
41
+ userInterfaceStyle: style == "light" ? .light : style == "dark" ? .dark : .unspecified
42
+ )
43
+ }
44
+
45
+ func projectAppearance() -> Appearance {
46
+ guard let configPath = launchArgument("--bleam-project-config") else {
47
+ return .default
48
+ }
49
+
50
+ do {
51
+ let data = try Data(contentsOf: URL(fileURLWithPath: configPath))
52
+ let value = try JSONSerialization.jsonObject(with: data) as? [String: Any]
53
+ return parseAppearance(from: value?["appearance"])
54
+ } catch {
55
+ return .default
56
+ }
57
+ }
58
+
59
+ func applyRootAppearance(to rootView: UIView) {
60
+ rootView.backgroundColor = .clear
61
+ rootView.isOpaque = false
62
+ }
@@ -0,0 +1,3 @@
1
+ //
2
+ // Use this file to import your target's public headers that you would like to expose to Swift.
3
+ //
@@ -0,0 +1,13 @@
1
+ {
2
+ "images" : [
3
+ {
4
+ "idiom" : "universal",
5
+ "platform" : "ios",
6
+ "size" : "1024x1024"
7
+ }
8
+ ],
9
+ "info" : {
10
+ "version" : 1,
11
+ "author" : "expo"
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "info" : {
3
+ "version" : 1,
4
+ "author" : "expo"
5
+ }
6
+ }
@@ -0,0 +1,76 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CADisableMinimumFrameDurationOnPhone</key>
6
+ <true/>
7
+ <key>CFBundleDevelopmentRegion</key>
8
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>$(PRODUCT_NAME)</string>
17
+ <key>CFBundleDisplayName</key>
18
+ <string>Bleam</string>
19
+ <key>CFBundlePackageType</key>
20
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
21
+ <key>CFBundleShortVersionString</key>
22
+ <string>1.0</string>
23
+ <key>CFBundleSignature</key>
24
+ <string>????</string>
25
+ <key>CFBundleVersion</key>
26
+ <string>1</string>
27
+ <key>AppGroupIdentifier</key>
28
+ <string>group.dev.bleam.app</string>
29
+ <key>LSMinimumSystemVersion</key>
30
+ <string>12.0</string>
31
+ <key>LSRequiresIPhoneOS</key>
32
+ <true/>
33
+ <key>NSAppTransportSecurity</key>
34
+ <dict>
35
+ <key>NSAllowsArbitraryLoads</key>
36
+ <false/>
37
+ <key>NSAllowsLocalNetworking</key>
38
+ <true/>
39
+ </dict>
40
+ <key>RCTNewArchEnabled</key>
41
+ <true/>
42
+ <key>UILaunchStoryboardName</key>
43
+ <string>SplashScreen</string>
44
+ <key>UIRequiredDeviceCapabilities</key>
45
+ <array>
46
+ <string>arm64</string>
47
+ </array>
48
+ <key>UIStatusBarStyle</key>
49
+ <string>UIStatusBarStyleDefault</string>
50
+ <key>UIApplicationSceneManifest</key>
51
+ <dict>
52
+ <key>UIApplicationSupportsMultipleScenes</key>
53
+ <false/>
54
+ <key>UISceneConfigurations</key>
55
+ <dict>
56
+ <key>UIWindowSceneSessionRoleApplication</key>
57
+ <array>
58
+ <dict>
59
+ <key>UISceneConfigurationName</key>
60
+ <string>Default Configuration</string>
61
+ <key>UISceneDelegateClassName</key>
62
+ <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
63
+ </dict>
64
+ </array>
65
+ </dict>
66
+ </dict>
67
+ <key>UISupportedInterfaceOrientations</key>
68
+ <array>
69
+ <string>UIInterfaceOrientationPortrait</string>
70
+ <string>UIInterfaceOrientationLandscapeLeft</string>
71
+ <string>UIInterfaceOrientationLandscapeRight</string>
72
+ </array>
73
+ <key>UIViewControllerBasedStatusBarAppearance</key>
74
+ <false/>
75
+ </dict>
76
+ </plist>
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>NSPrivacyAccessedAPITypes</key>
6
+ <array>
7
+ <dict>
8
+ <key>NSPrivacyAccessedAPIType</key>
9
+ <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
10
+ <key>NSPrivacyAccessedAPITypeReasons</key>
11
+ <array>
12
+ <string>CA92.1</string>
13
+ </array>
14
+ </dict>
15
+ <dict>
16
+ <key>NSPrivacyAccessedAPIType</key>
17
+ <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
18
+ <key>NSPrivacyAccessedAPITypeReasons</key>
19
+ <array>
20
+ <string>0A2A.1</string>
21
+ <string>3B52.1</string>
22
+ <string>C617.1</string>
23
+ </array>
24
+ </dict>
25
+ <dict>
26
+ <key>NSPrivacyAccessedAPIType</key>
27
+ <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
28
+ <key>NSPrivacyAccessedAPITypeReasons</key>
29
+ <array>
30
+ <string>E174.1</string>
31
+ <string>85F4.1</string>
32
+ </array>
33
+ </dict>
34
+ <dict>
35
+ <key>NSPrivacyAccessedAPIType</key>
36
+ <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
37
+ <key>NSPrivacyAccessedAPITypeReasons</key>
38
+ <array>
39
+ <string>35F9.1</string>
40
+ </array>
41
+ </dict>
42
+ </array>
43
+ <key>NSPrivacyCollectedDataTypes</key>
44
+ <array/>
45
+ <key>NSPrivacyTracking</key>
46
+ <false/>
47
+ </dict>
48
+ </plist>
@@ -0,0 +1,58 @@
1
+ internal import Expo
2
+ import React
3
+ import ReactAppDependencyProvider
4
+ import UIKit
5
+
6
+ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
7
+ var window: UIWindow?
8
+ var reactNativeDelegate: ReactNativeDelegate?
9
+ var reactNativeFactory: ExpoReactNativeFactory?
10
+
11
+ func scene(
12
+ _ scene: UIScene,
13
+ willConnectTo _: UISceneSession,
14
+ options _: UIScene.ConnectionOptions
15
+ ) {
16
+ guard let windowScene = scene as? UIWindowScene else {
17
+ return
18
+ }
19
+
20
+ let bundleURL = SceneDelegate.bundleURL()
21
+ let title = launchArgument("--bleam-title")
22
+ let appearance = projectAppearance()
23
+
24
+ let delegate = ReactNativeDelegate(bundleURL: bundleURL)
25
+ let factory = ExpoReactNativeFactory(delegate: delegate)
26
+ delegate.dependencyProvider = RCTAppDependencyProvider()
27
+
28
+ let window = UIWindow(windowScene: windowScene)
29
+ if let windowBackgroundColor = appearance.windowBackgroundColor {
30
+ window.backgroundColor = windowBackgroundColor
31
+ }
32
+ window.overrideUserInterfaceStyle = appearance.userInterfaceStyle
33
+ factory.startReactNative(
34
+ withModuleName: "main",
35
+ in: window,
36
+ initialProperties: [:],
37
+ launchOptions: nil
38
+ )
39
+ window.rootViewController?.overrideUserInterfaceStyle = appearance.userInterfaceStyle
40
+ if let rootView = window.rootViewController?.view {
41
+ applyRootAppearance(to: rootView)
42
+ }
43
+ window.rootViewController?.title = title ?? "Bleam"
44
+
45
+ self.window = window
46
+ reactNativeDelegate = delegate
47
+ reactNativeFactory = factory
48
+ OTAUpdateManager.shared.checkForUpdate()
49
+ }
50
+
51
+ private static func bundleURL() -> URL? {
52
+ guard let bundleURLString = launchArgument("--bleam-bundle-url") else {
53
+ return nil
54
+ }
55
+
56
+ return URL(string: bundleURLString)
57
+ }
58
+ }