-
Notifications
You must be signed in to change notification settings - Fork 31
feat: unify expo and bare RN in ReactNativeBrownfield #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
114 commits
Select commit
Hold shift + click to select a range
61271cb
chore: bootstrapped demo Expo app
artus9033 0282537
chore: use expo config plugin in expo demo app
artus9033 a9dbb08
chore: reset Expo project
artus9033 9c92eaa
chore: use workspace specifier for monorepo deps
artus9033 4a5702a
fix: do not toss up source sets in Gradle plugin
artus9033 4893be4
feat: base implementation for brownfield Expo config plugin
artus9033 a65a9f1
chore: update lock files
artus9033 6aba560
chore: update app.json in ExpoApp
artus9033 f30f055
chore: enable debug logging in app.json in ExpoApp
artus9033 594aaf5
feat: use new logging system in the plugin
artus9033 9e0ba69
feat: templates engine for project modifications
artus9033 a5840e9
feat: patch for Expo SDK pre v55, fix source file paths
artus9033 b544e47
feat: implemented Android brownfield plugin
artus9033 af69bca
chore: update ExpoApp scripts
artus9033 2afa209
fix: dedent gradle script insertion
artus9033 64eb48d
fix: depend on Material in AndroidApp; fix typo in gradle scripting c…
artus9033 23e4c8e
fix: package name in ExpoApp
artus9033 95b580c
chore: use debug signing config for AndroidApp release variant - for …
artus9033 a066b02
chore: missing indent in gradleHelpers insertion
artus9033 0f34957
fix: add missing expo modifications to template build.gradle.kts
artus9033 0a9c3ca
chore: use the Expo classes in template ReactNativeHostManager.kt
artus9033 080a124
fix: iOS xcode project processing of target UUID
artus9033 834d850
fix: make Android Expo config explicitly specify versions of RN Andro…
artus9033 a4c0913
fix: running package:ios again
thymikee ccf8f48
chore: udpate rock to 0.12.8
thymikee 4bf29e7
chore: make nodemon watch template files in dev script for brownfield…
artus9033 ac7abeb
chore: reformat files, extract capitalized string helper, suppress un…
artus9033 d9050d5
chore: deintegrate isExpo gradle plugin prop in favor of auto-detection
artus9033 c2648c7
chore: typo in Android native demo app theme name
artus9033 4a59b38
feat: config Maven publishing for part of the core expo modules
artus9033 74b0d80
fix: correct artifact, group and version discovery for manually white…
artus9033 7d9f2f7
feat: inject transitive dependencies into POM publication files
artus9033 619eb2b
feat: instead of publishing, inject proper POM and Gradle Module JSON…
artus9033 1d36921
feat: functional Expo demo in AndroidApp
artus9033 310a7b2
chore: re-enable signing of gradle plugin
artus9033 1867458
chore: use 0.0.1-snapshot by default in Expo plugin on Android
artus9033 09c0dce
fix: filter out remaining expo transitive dependencies, add version m…
artus9033 2ce1d5b
feat: seamless integration of Expo features into the brownfield CLI
artus9033 1985835
refactor: restructure RNApp sources
artus9033 a64e2fe
feat: reuse RNApp sources in ExpoApp
artus9033 adf3ea3
feat: set up flavors for AndroidApp to consume expo or vanilla artifacts
artus9033 957b5ff
ci: update CI to account for AndroidApp flavors
artus9033 9390219
chore: remove obsolete comment
artus9033 7bbc2d1
fix: monorepo-prone expo detection in CLI
artus9033 e214f81
feat: proper code sharing for RN demo apps
artus9033 c52ce57
fix: make ReactNativeHostManager singatures match across flavors, pro…
artus9033 4456f06
fix: restore .brownie.ts files in each project for codegen to work pr…
artus9033 f0adf90
feat: added an image view to the demo app
artus9033 341f535
chore: strip obsolete comment
artus9033 580b19c
fix: proper module name in ios script
artus9033 5a21b7c
fix: brownie not to crash on Android
artus9033 afad19d
fix: handle brownie no stores in project in the CLI
artus9033 b6ba4b7
feat: demo apps reorganized, pulled in clean template for expo app
artus9033 69b6497
feat: integrate brownie store with Expo demo app
artus9033 470be26
docs: update docs
artus9033 a4cd611
Merge branch 'main' into feat/expo-config-plugin
artus9033 7c3b790
feat: temporarily deintegrate brownie from expo demo before android i…
artus9033 48fd6e1
Merge branch 'main' into feat/expo-config-plugin
artus9033 2b1680c
chore: rename expo app project
artus9033 6058678
chore: re-enable signing of the gradle plugin
artus9033 77726ee
chore: add changesets
artus9033 6f7cb58
refactor: format files
artus9033 9a274d1
fix(ci): path to RN project in androidapp-road-test
artus9033 e08a74c
refactor: format files to comply with detekt
artus9033 0f6d0b6
chore: revert changes to brownie
artus9033 27fb93c
fix: paths in packageIos in RN projects
artus9033 d867bb3
ci: update workflow for Apple apps
artus9033 24db114
feat: demo iOS app supporting interchanging brownfield artifacts
artus9033 0989c60
fix: patchExpoPre55.sh
artus9033 f4a44b8
fix: reorder build phases in iOS to first run patching after expo con…
artus9033 54fa5fc
wip: reorder build script phases PoC for Expo config plugin
artus9033 6d86267
chore: reorder code properly
artus9033 4f20e9d
chore: use SNAPSHOT for CI and local
hurali97 9613fda
chore: add plugin publish and patch scripts for local maven
hurali97 a633cc6
chore: fix appleapp-road-test ci
hurali97 6d322d1
chore: use macos runner for appleapp CI
hurali97 515c3fc
fix(ci): update maven path for expo flavor
hurali97 36771bd
fix(ci): expo android
hurali97 ffbb9d6
feat: ensure build phase correct order using post_integrate
hurali97 9bc4954
feat: add ReactNativeHostManager to source files
hurali97 a5bae9c
fix: use the bundleURL in loadView
hurali97 70f910f
feat: present Expo RN UI in Apple App
hurali97 b7f3049
Merge branch 'main' of github.com:callstack/react-native-brownfield i…
hurali97 52e18f2
chore: use latest version for brownfield-gradle-plugin
hurali97 5504dd1
feat: add source files to PBXSourcesBuildPhase
hurali97 e921555
feat: allow entry points other than main
hurali97 8a9e58f
feat: add configuration for vanilla and expo to AppleApp
hurali97 45bbe35
fix: add info.plist to AppleApp
hurali97 881ee41
fix: bundle reference
hurali97 0588c3c
fix(ci): add guard to only run pods for vanilla
hurali97 250d8a0
docs: update ExpoApp usages
hurali97 fee1c47
feat: remove coil dependency from plugin to the lib
hurali97 f155923
refactor: remove TODO comments
hurali97 ec05bba
feat: guard script reordering against expo version
hurali97 1f6bbcb
feat: separate brownie usage by platform
hurali97 f9bf078
chore: build android app with release variant
hurali97 1734e3e
docs: add Expo Integration section
hurali97 1d50f6b
chore: bump versions
hurali97 6516315
fix: remove color prop
hurali97 0abb3f7
Update docs/docs/docs/getting-started/expo.mdx
hurali97 93cc1a3
Update docs/docs/docs/getting-started/expo.mdx
hurali97 8602909
docs: remove images
hurali97 0ee3099
refactor: fix indentation
hurali97 9cb4284
feat: unify expo and bare RN in ReactNativeBrownfield
hurali97 4c5c3e7
Merge branch 'main' of github.com:callstack/react-native-brownfield i…
hurali97 96badd9
chore: remove changeset bump
hurali97 dde6558
refactor: remove unused property and enforce failure
hurali97 71ee9e6
refactor: split classes by concerns
hurali97 4347a54
refactor: move duplicate code to a shareable resource
hurali97 903658c
fix: make the class internal
hurali97 d4420f4
chore: podfile changes
hurali97 594e60a
feat: add JSBundle load for Expo and make it reusable
hurali97 86c077e
fix: fail early for non-extension bundle path
hurali97 0d55c6d
docs: update
hurali97 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
packages/react-native-brownfield/ios/BrownfieldBundlePathResolver.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import Foundation | ||
|
|
||
| enum BrownfieldBundlePathResolver { | ||
| enum Error: Swift.Error { | ||
| case invalidBundlePath(String) | ||
| } | ||
|
|
||
| static func resourceComponents(from bundlePath: String) throws -> ( | ||
| resourceName: String, | ||
| fileExtension: String | ||
| ) { | ||
| let fileExtension = (bundlePath as NSString).pathExtension | ||
| let resourceName = (bundlePath as NSString).deletingPathExtension | ||
|
|
||
| guard !fileExtension.isEmpty, !resourceName.isEmpty else { | ||
| throw Error.invalidBundlePath(bundlePath) | ||
| } | ||
|
|
||
| return (resourceName, fileExtension) | ||
| } | ||
| } |
140 changes: 140 additions & 0 deletions
140
packages/react-native-brownfield/ios/ExpoHostRuntime.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| import UIKit | ||
| internal import React | ||
| internal import React_RCTAppDelegate | ||
| internal import ReactAppDependencyProvider | ||
|
|
||
| #if canImport(Expo) | ||
| internal import Expo | ||
|
|
||
| final class ExpoHostRuntime { | ||
| static let shared = ExpoHostRuntime() | ||
|
|
||
| private let jsBundleLoadObserver = JSBundleLoadObserver() | ||
| private var delegate = ExpoHostRuntimeDelegate() | ||
| private var reactNativeFactory: RCTReactNativeFactory? | ||
| private var expoDelegate: ExpoAppDelegate? | ||
|
|
||
| /** | ||
| * Starts React Native with default parameters. | ||
| */ | ||
| public func startReactNative() { | ||
| startReactNative(onBundleLoaded: nil) | ||
| } | ||
| /** | ||
| * Starts React Native with optional callback when bundle is loaded. | ||
| * | ||
| * @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded. | ||
| */ | ||
| public func startReactNative(onBundleLoaded: (() -> Void)?) { | ||
| guard reactNativeFactory == nil else { return } | ||
|
|
||
| let factory = ExpoReactNativeFactory(delegate: delegate) | ||
| delegate.dependencyProvider = RCTAppDependencyProvider() | ||
|
|
||
| reactNativeFactory = factory | ||
|
|
||
| let appDelegate = ExpoAppDelegate() | ||
| appDelegate.bindReactNativeFactory(factory) | ||
| expoDelegate = appDelegate | ||
|
|
||
| if let onBundleLoaded { | ||
| jsBundleLoadObserver.observeOnce(onBundleLoaded: onBundleLoaded) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Path to JavaScript root. | ||
| * Default value: ".expo/.virtual-metro-entry" | ||
| */ | ||
| public var entryFile: String = ".expo/.virtual-metro-entry" { | ||
| didSet { | ||
| delegate.entryFile = entryFile | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Path to JavaScript bundle file. | ||
| * Default value: "main.jsbundle" | ||
| */ | ||
| public var bundlePath: String = "main.jsbundle" { | ||
| didSet { | ||
| delegate.bundlePath = bundlePath | ||
| } | ||
| } | ||
| /** | ||
| * Bundle instance to lookup the JavaScript bundle. | ||
| * Default value: Bundle.main | ||
| */ | ||
| public var bundle: Bundle = Bundle.main { | ||
| didSet { | ||
| delegate.bundle = bundle | ||
| } | ||
| } | ||
| /** | ||
| * Dynamic bundle URL provider called on every bundle load. | ||
| * When set, this overrides the default bundleURL() behavior in the delegate. | ||
| * Returns a URL to load a custom bundle, or nil to use default behavior. | ||
| * Default value: nil | ||
| */ | ||
| public var bundleURLOverride: (() -> URL?)? = nil { | ||
| didSet { | ||
| delegate.bundleURLOverride = bundleURLOverride | ||
| } | ||
| } | ||
|
|
||
| func application( | ||
| _ application: UIApplication, | ||
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil | ||
| ) -> Bool { | ||
| return expoDelegate?.application( | ||
| application, | ||
| didFinishLaunchingWithOptions: launchOptions | ||
| ) != nil | ||
| } | ||
|
|
||
| func view( | ||
| moduleName: String, | ||
| initialProps: [AnyHashable: Any]?, | ||
| launchOptions: [AnyHashable: Any]? | ||
| ) -> UIView? { | ||
| let bundleURL = delegate.bundleURL() | ||
|
|
||
| return expoDelegate?.recreateRootView( | ||
| withBundleURL: bundleURL, | ||
| moduleName: moduleName, | ||
| initialProps: initialProps, | ||
| launchOptions: launchOptions | ||
| ) | ||
| } | ||
hurali97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| class ExpoHostRuntimeDelegate: ExpoReactNativeFactoryDelegate { | ||
| var entryFile = ".expo/.virtual-metro-entry" | ||
| var bundlePath = "main.jsbundle" | ||
| var bundle = Bundle.main | ||
| var bundleURLOverride: (() -> URL?)? = nil | ||
|
|
||
| override func sourceURL(for bridge: RCTBridge) -> URL? { | ||
| // needed to return the correct URL for expo-dev-client. | ||
| bridge.bundleURL ?? bundleURL() | ||
| } | ||
|
|
||
| override func bundleURL() -> URL? { | ||
| if let bundleURLProvider = bundleURLOverride { return bundleURLProvider() } | ||
| #if DEBUG | ||
| return RCTBundleURLProvider.sharedSettings().jsBundleURL( | ||
| forBundleRoot: entryFile) | ||
| #else | ||
| do { | ||
| let (resourceName, fileExtension) = try BrownfieldBundlePathResolver.resourceComponents( | ||
| from: bundlePath | ||
| ) | ||
| return bundle.url(forResource: resourceName, withExtension: fileExtension) | ||
| } catch { | ||
| assertionFailure("Invalid bundlePath '\(bundlePath)': \(error)") | ||
| return nil | ||
| } | ||
| #endif | ||
| } | ||
| } | ||
| #endif | ||
38 changes: 38 additions & 0 deletions
38
packages/react-native-brownfield/ios/JSBundleLoadObserver.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import Foundation | ||
| internal import React | ||
|
|
||
| final class JSBundleLoadObserver { | ||
| private var onBundleLoaded: (() -> Void)? | ||
| private var observerToken: NSObjectProtocol? | ||
|
|
||
| func observeOnce(onBundleLoaded: @escaping () -> Void) { | ||
| removeObserverIfNeeded() | ||
| self.onBundleLoaded = onBundleLoaded | ||
|
|
||
| observerToken = NotificationCenter.default.addObserver( | ||
| forName: NSNotification.Name("RCTInstanceDidLoadBundle"), | ||
| object: nil, | ||
| queue: nil | ||
| ) { [weak self] _ in | ||
| self?.notifyAndClear() | ||
| } | ||
| } | ||
|
|
||
| deinit { | ||
| removeObserverIfNeeded() | ||
| } | ||
|
|
||
| private func notifyAndClear() { | ||
| let callback = onBundleLoaded | ||
| onBundleLoaded = nil | ||
| removeObserverIfNeeded() | ||
| callback?() | ||
| } | ||
|
|
||
| private func removeObserverIfNeeded() { | ||
| if let observerToken { | ||
| NotificationCenter.default.removeObserver(observerToken) | ||
| self.observerToken = nil | ||
| } | ||
| } | ||
| } |
12 changes: 12 additions & 0 deletions
12
packages/react-native-brownfield/ios/Notification+Brownfield.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import Foundation | ||
|
|
||
| extension Notification.Name { | ||
| /** | ||
| * Notification sent when React Native wants to navigate back to native screen. | ||
| */ | ||
| public static let popToNative = Notification.Name("PopToNativeNotification") | ||
| /** | ||
| * Notification sent to enable/disable the pop gesture recognizer. | ||
| */ | ||
| public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification") | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.