diff --git a/swift/apple/Firezone/Application/FirezoneApp.swift b/swift/apple/Firezone/Application/FirezoneApp.swift index ac6d32b87..a24f7d63a 100644 --- a/swift/apple/Firezone/Application/FirezoneApp.swift +++ b/swift/apple/Firezone/Application/FirezoneApp.swift @@ -36,7 +36,10 @@ struct FirezoneApp: App { "Welcome to Firezone", id: AppViewModel.WindowDefinition.main.identifier ) { - AppView(model: appViewModel) + if let menuBar = appDelegate.menuBar { + // menuBar will be initialized by this point + AppView(model: appViewModel).environmentObject(menuBar) + } } .handlesExternalEvents( matching: [AppViewModel.WindowDefinition.main.externalEventMatchString] @@ -58,7 +61,7 @@ struct FirezoneApp: App { #if os(macOS) @MainActor final class AppDelegate: NSObject, NSApplicationDelegate { - private var menuBar: MenuBar? + var menuBar: MenuBar? public var store: Store? func applicationDidFinishLaunching(_: Notification) { diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/FirstTimeView.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/FirstTimeView.swift index dd6e4103b..d23bd9f17 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/FirstTimeView.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/FirstTimeView.swift @@ -9,6 +9,8 @@ import SwiftUI #if os(macOS) struct FirstTimeView: View { + @EnvironmentObject var menuBar: MenuBar + var body: some View { VStack( alignment: .center, @@ -21,17 +23,27 @@ struct FirstTimeView: View { .padding(.horizontal, 10) Spacer() Text( - "You can sign in to Firezone by clicking on the Firezone icon in the macOS menu bar.\nYou may now close this window." + "You can sign in by clicking the Firezone icon in the macOS menu bar or clicking 'Open menu' below." ) .font(.body) .multilineTextAlignment(.center) Spacer() - Button("Close this Window") { - AppViewModel.WindowDefinition.main.window()?.close() + HStack { + Button("Close this window") { + AppViewModel.WindowDefinition.main.window()?.close() + } + .buttonStyle(.borderedProminent) + .controlSize(.large) + Button("Open menu") { + DispatchQueue.main.async { + menuBar.showMenu() + } + AppViewModel.WindowDefinition.main.window()?.close() + } + .buttonStyle(.borderedProminent) + .controlSize(.large) } - .buttonStyle(.borderedProminent) - .controlSize(.large) Spacer() .frame(maxHeight: 20) Text( diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/MenuBar.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/MenuBar.swift index 0f53cbed1..347fac208 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/MenuBar.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/MenuBar.swift @@ -16,7 +16,7 @@ import SwiftUI @MainActor // TODO: Refactor to MenuBarExtra for macOS 13+ // https://developer.apple.com/documentation/swiftui/menubarextra -public final class MenuBar: NSObject { +public final class MenuBar: NSObject, ObservableObject { private var statusItem: NSStatusItem private var resources: [Resource]? private var cancellables: Set = [] @@ -48,6 +48,10 @@ public final class MenuBar: NSObject { setupObservers() } + func showMenu() { + statusItem.button?.performClick(nil) + } + private func setupObservers() { model.store.$status .receive(on: DispatchQueue.main)