Skip to content

Commit 8e71743

Browse files
committed
fix: allow to manually move dev menu to avoid conflicts (#150)
1 parent 640763b commit 8e71743

File tree

3 files changed

+50
-41
lines changed

3 files changed

+50
-41
lines changed

packages/react-native/Libraries/SwiftExtensions/RCTMainWindow.swift

+6-38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import SwiftUI
2-
import React
32

43
/**
54
This SwiftUI struct returns main React Native scene. It should be used only once as it conains setup code.
@@ -22,11 +21,11 @@ public struct RCTMainWindow: Scene {
2221
var moduleName: String
2322
var initialProps: RCTRootViewRepresentable.InitialPropsType
2423
var onOpenURLCallback: ((URL) -> ())?
25-
var devMenuPlacement: ToolbarPlacement = .bottomOrnament
24+
var devMenuSceneAnchor: UnitPoint?
2625
var contentView: AnyView?
2726

2827
var rootView: RCTRootViewRepresentable {
29-
RCTRootViewRepresentable(moduleName: moduleName, initialProps: initialProps)
28+
RCTRootViewRepresentable(moduleName: moduleName, initialProps: initialProps, devMenuSceneAnchor: devMenuSceneAnchor)
3029
}
3130

3231
/// Creates new RCTMainWindowWindow.
@@ -38,11 +37,11 @@ public struct RCTMainWindow: Scene {
3837
public init(
3938
moduleName: String,
4039
initialProps: RCTRootViewRepresentable.InitialPropsType = nil,
41-
devMenuPlacement: ToolbarPlacement = .bottomOrnament
40+
devMenuSceneAnchor: UnitPoint? = .bottom
4241
) {
4342
self.moduleName = moduleName
4443
self.initialProps = initialProps
45-
self.devMenuPlacement = devMenuPlacement
44+
self.devMenuSceneAnchor = devMenuSceneAnchor
4645
self.contentView = AnyView(rootView)
4746
}
4847

@@ -56,12 +55,12 @@ public struct RCTMainWindow: Scene {
5655
public init<Content: View>(
5756
moduleName: String,
5857
initialProps: RCTRootViewRepresentable.InitialPropsType = nil,
59-
devMenuPlacement: ToolbarPlacement = .bottomOrnament,
58+
devMenuSceneAnchor: UnitPoint? = .bottom,
6059
@ViewBuilder contentView: @escaping (_ view: RCTRootViewRepresentable) -> Content
6160
) {
6261
self.moduleName = moduleName
6362
self.initialProps = initialProps
64-
self.devMenuPlacement = devMenuPlacement
63+
self.devMenuSceneAnchor = devMenuSceneAnchor
6564
self.contentView = AnyView(contentView(rootView))
6665
}
6766

@@ -72,11 +71,6 @@ public struct RCTMainWindow: Scene {
7271
.onOpenURL(perform: { url in
7372
onOpenURLCallback?(url)
7473
})
75-
#if DEBUG
76-
.toolbar {
77-
DevMenuView(placement: .bottomOrnament)
78-
}
79-
#endif
8074
}
8175
}
8276
}
@@ -139,29 +133,3 @@ public struct WindowHandlingModifier: ViewModifier {
139133
}
140134
}
141135

142-
/**
143-
Toolbar which displays additional controls to easily open dev menu and trigger reload command.
144-
*/
145-
struct DevMenuView: ToolbarContent {
146-
let placement: ToolbarItemPlacement
147-
148-
var body: some ToolbarContent {
149-
ToolbarItem(placement: placement) {
150-
Button(action: {
151-
RCTTriggerReloadCommandListeners("User Reload")
152-
}, label: {
153-
Image(systemName: "arrow.clockwise")
154-
})
155-
}
156-
ToolbarItem(placement: placement) {
157-
Button(action: {
158-
NotificationCenter.default.post(
159-
Notification(name: Notification.Name("RCTShowDevMenuNotification"), object: nil)
160-
)
161-
},
162-
label: {
163-
Image(systemName: "filemenu.and.selection")
164-
})
165-
}
166-
}
167-
}

packages/react-native/Libraries/SwiftExtensions/RCTRootViewRepresentable.swift

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import SwiftUI
2+
import React
23

34
/**
45
SwiftUI view enclosing `RCTReactViewController`. Its main purpose is to display React Native views inside of SwiftUI lifecycle.
@@ -16,17 +17,57 @@ public struct RCTRootViewRepresentable: UIViewControllerRepresentable {
1617

1718
var moduleName: String
1819
var initialProps: InitialPropsType
20+
var devMenuSceneAnchor: UnitPoint?
1921

20-
public init(moduleName: String, initialProps: InitialPropsType = nil) {
22+
public init(
23+
moduleName: String,
24+
initialProps: InitialPropsType = nil,
25+
devMenuSceneAnchor: UnitPoint? = .bottom
26+
) {
2127
self.moduleName = moduleName
2228
self.initialProps = initialProps
29+
self.devMenuSceneAnchor = devMenuSceneAnchor
2330
}
2431

2532
public func makeUIViewController(context: Context) -> RCTReactViewController {
26-
RCTReactViewController(moduleName: moduleName, initProps: initialProps)
33+
let viewController = RCTReactViewController(moduleName: moduleName, initProps: initialProps)
34+
#if DEBUG
35+
if let devMenuSceneAnchor {
36+
let ornament = UIHostingOrnament(sceneAnchor: devMenuSceneAnchor) {
37+
DevMenuView()
38+
}
39+
viewController.ornaments.append(ornament)
40+
}
41+
#endif
42+
return viewController
2743
}
2844

2945
public func updateUIViewController(_ uiViewController: RCTReactViewController, context: Context) {
3046
uiViewController.updateProps(initialProps)
3147
}
3248
}
49+
50+
/**
51+
Toolbar which displays additional controls to easily open dev menu and trigger reload command.
52+
*/
53+
struct DevMenuView: View {
54+
var body: some View {
55+
HStack {
56+
Button(action: {
57+
RCTTriggerReloadCommandListeners("User Reload")
58+
}, label: {
59+
Image(systemName: "arrow.clockwise")
60+
})
61+
Button(action: {
62+
NotificationCenter.default.post(
63+
Notification(name: Notification.Name("RCTShowDevMenuNotification"), object: nil)
64+
)
65+
},
66+
label: {
67+
Image(systemName: "filemenu.and.selection")
68+
})
69+
}
70+
.padding()
71+
.glassBackgroundEffect()
72+
}
73+
}

packages/react-native/Libraries/SwiftExtensions/RCTWindow.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public struct RCTWindow : Scene {
1616
var contentView: AnyView?
1717

1818
func getRootView(sceneData: RCTSceneData?) -> RCTRootViewRepresentable {
19-
return RCTRootViewRepresentable(moduleName: moduleName, initialProps: sceneData?.props ?? [:])
19+
return RCTRootViewRepresentable(moduleName: moduleName, initialProps: sceneData?.props ?? [:], devMenuSceneAnchor: nil)
2020
}
2121

2222
public var body: some Scene {

0 commit comments

Comments
 (0)