Skip to content

Commit d081e3b

Browse files
committed
feat: consume brownfield navigation
1 parent 3f6858a commit d081e3b

9 files changed

Lines changed: 274 additions & 72 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "2620"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES"
8+
buildArchitectures = "Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting = "YES"
12+
buildForRunning = "YES"
13+
buildForProfiling = "YES"
14+
buildForArchiving = "YES"
15+
buildForAnalyzing = "YES">
16+
<BuildableReference
17+
BuildableIdentifier = "primary"
18+
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
19+
BuildableName = "Brownfield Apple App.app"
20+
BlueprintName = "Brownfield Apple App"
21+
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
25+
</BuildAction>
26+
<TestAction
27+
buildConfiguration = "Debug"
28+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
29+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Release"
35+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37+
launchStyle = "0"
38+
useCustomWorkingDirectory = "NO"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
debugServiceExtension = "internal"
42+
allowLocationSimulation = "YES">
43+
<BuildableProductRunnable
44+
runnableDebuggingMode = "0">
45+
<BuildableReference
46+
BuildableIdentifier = "primary"
47+
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
48+
BuildableName = "Brownfield Apple App.app"
49+
BlueprintName = "Brownfield Apple App"
50+
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
51+
</BuildableReference>
52+
</BuildableProductRunnable>
53+
</LaunchAction>
54+
<ProfileAction
55+
buildConfiguration = "Release"
56+
shouldUseLaunchSchemeArgsEnv = "YES"
57+
savedToolIdentifier = ""
58+
useCustomWorkingDirectory = "NO"
59+
debugDocumentVersioning = "YES">
60+
<BuildableProductRunnable
61+
runnableDebuggingMode = "0">
62+
<BuildableReference
63+
BuildableIdentifier = "primary"
64+
BlueprintIdentifier = "793C76A62EEBF938008A2A34"
65+
BuildableName = "Brownfield Apple App.app"
66+
BlueprintName = "Brownfield Apple App"
67+
ReferencedContainer = "container:Brownfield Apple App.xcodeproj">
68+
</BuildableReference>
69+
</BuildableProductRunnable>
70+
</ProfileAction>
71+
<AnalyzeAction
72+
buildConfiguration = "Debug">
73+
</AnalyzeAction>
74+
<ArchiveAction
75+
buildConfiguration = "Release"
76+
revealArchiveInOrganizer = "YES">
77+
</ArchiveAction>
78+
</Scheme>

apps/AppleApp/Brownfield Apple App/BrownfieldAppleApp.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,61 @@ import BrownfieldLib
22
import Brownie
33
import ReactBrownfield
44
import SwiftUI
5+
import UIKit
56

67
class AppDelegate: NSObject, UIApplicationDelegate {
78
var window: UIWindow?
89
}
910

11+
public class RNNavigationDelegate: BrownfieldNavigationDelegate {
12+
public func navigateToSettings() {
13+
present(SettingsScreen())
14+
}
15+
16+
public func navigateToReferrals(userId: String) {
17+
present(ReferralsScreen(userId: userId))
18+
}
19+
20+
private func present<Content: View>(_ view: Content) {
21+
DispatchQueue.main.async {
22+
let hostingController = UIHostingController(rootView: view)
23+
24+
guard let topController = UIApplication.shared.topMostViewController() else {
25+
return
26+
}
27+
28+
if let navigationController = topController.navigationController {
29+
navigationController.pushViewController(hostingController, animated: true)
30+
return
31+
}
32+
33+
let navigationController = UINavigationController(rootViewController: hostingController)
34+
topController.present(navigationController, animated: true)
35+
}
36+
}
37+
}
38+
39+
private extension UIApplication {
40+
func topMostViewController(
41+
base: UIViewController? = UIApplication.shared.connectedScenes
42+
.compactMap { $0 as? UIWindowScene }
43+
.flatMap { $0.windows }
44+
.first(where: { $0.isKeyWindow })?.rootViewController
45+
) -> UIViewController? {
46+
if let navigationController = base as? UINavigationController {
47+
return topMostViewController(base: navigationController.visibleViewController)
48+
}
49+
if let tabBarController = base as? UITabBarController,
50+
let selected = tabBarController.selectedViewController {
51+
return topMostViewController(base: selected)
52+
}
53+
if let presented = base?.presentedViewController {
54+
return topMostViewController(base: presented)
55+
}
56+
return base
57+
}
58+
}
59+
1060
@main
1161
struct BrownfieldAppleApp: App {
1262
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@@ -16,6 +66,21 @@ struct BrownfieldAppleApp: App {
1666
ReactNativeBrownfield.shared.startReactNative {
1767
print("React Native has been loaded")
1868
}
69+
70+
// let mgr = ReactBrownfield.BrownfieldNavigationManager.shared
71+
// print("SWIFT mgr:", Unmanaged.passUnretained(mgr).toOpaque())
72+
// print("SWIFT class:", NSStringFromClass(type(of: mgr)))
73+
// print("SWIFT bundle:", Bundle(for: ReactBrownfield.BrownfieldNavigationManager.self).bundlePath)
74+
// ReactBrownfield.BrownfieldNavigationManager.shared.setDelegate(navigationDelegate: RNNavigationDelegate())
75+
76+
let mgr = BrownfieldNavigationManager.shared
77+
print("11 SWIFT mgr:", Unmanaged.passUnretained(mgr).toOpaque())
78+
print("11 SWIFT class:", NSStringFromClass(type(of: mgr)))
79+
print("11 SWIFT bundle:", Bundle(for: BrownfieldNavigationManager.self).bundlePath)
80+
81+
mgr.setDelegate(
82+
navigationDelegate: RNNavigationDelegate()
83+
)
1984

2085
BrownfieldStore.register(initialState)
2186
}

apps/AppleApp/Brownfield Apple App/ContentView.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct ContentView: View {
1717
}
1818

1919
struct MainScreen: View {
20+
2021
var body: some View {
2122
VStack(spacing: 16) {
2223
GreetingCard(name: "iOS")
@@ -31,6 +32,53 @@ struct MainScreen: View {
3132
}
3233
}
3334

35+
struct SettingsScreen: View {
36+
var body: some View {
37+
Form {
38+
Section("Preferences") {
39+
Toggle("Enable notifications", isOn: .constant(true))
40+
Toggle("Dark mode", isOn: .constant(false))
41+
}
42+
43+
Section("About") {
44+
HStack {
45+
Text("Version")
46+
Spacer()
47+
Text("1.0.0")
48+
.foregroundStyle(.secondary)
49+
}
50+
}
51+
}
52+
.navigationTitle("Settings")
53+
}
54+
}
55+
56+
struct ReferralsScreen: View {
57+
let userId: String
58+
59+
var body: some View {
60+
VStack(spacing: 16) {
61+
Text("Referrals")
62+
.font(.title2)
63+
.fontWeight(.semibold)
64+
65+
Text("User ID")
66+
.foregroundStyle(.secondary)
67+
Text(userId)
68+
.font(.body.monospaced())
69+
.textSelection(.enabled)
70+
71+
Button("Share referral link") {
72+
// Placeholder action for the sample app.
73+
}
74+
.buttonStyle(.borderedProminent)
75+
}
76+
.frame(maxWidth: .infinity, maxHeight: .infinity)
77+
.padding()
78+
.navigationTitle("Referrals")
79+
}
80+
}
81+
3482
struct GreetingCard: View {
3583
let name: String
3684
@UseStore(\BrownfieldStore.counter) var counter

apps/RNApp/App.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type NativeStackScreenProps,
88
} from '@react-navigation/native-stack';
99
import ReactNativeBrownfield from '@callstack/react-native-brownfield';
10+
import { BrownfieldNavigation } from '@callstack/react-native-brownfield';
1011
import { NavigationContainer } from '@react-navigation/native';
1112

1213
const getRandomValue = () => Math.round(Math.random() * 255);
@@ -75,6 +76,18 @@ function HomeScreen({ navigation, route }: Props) {
7576
color={colors.secondary}
7677
title="Go back"
7778
/>
79+
80+
<Button
81+
onPress={() => BrownfieldNavigation.navigateToSettings()}
82+
color={colors.secondary}
83+
title="Open native settings"
84+
/>
85+
86+
<Button
87+
onPress={() => BrownfieldNavigation.navigateToReferrals('user-123')}
88+
color={colors.secondary}
89+
title="Open native referrals"
90+
/>
7891
</View>
7992
);
8093
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface BrownfieldNavigationSpec {
2+
/**
3+
* Navigate to the native settings screen
4+
*/
5+
navigateToSettings(): void;
6+
7+
/**
8+
* Navigate to the native referrals screen
9+
* @param userId - The user's unique identifier
10+
*/
11+
navigateToReferrals(userId: string): void;
12+
}

0 commit comments

Comments
 (0)