feat: make tray menu actions work and add functional demo sections
All checks were successful
swift-macos-arm64 / swift-macos-arm64 (push) Successful in 11s
All checks were successful
swift-macos-arm64 / swift-macos-arm64 (push) Successful in 11s
This commit is contained in:
parent
3ea7bab7bf
commit
44b59d50c9
@ -1,5 +1,32 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
enum DemoSection: String, CaseIterable, Identifiable, Hashable {
|
||||||
|
case overview
|
||||||
|
case windowControls
|
||||||
|
case secondaryWindow
|
||||||
|
case dialogs
|
||||||
|
|
||||||
|
var id: String { rawValue }
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
switch self {
|
||||||
|
case .overview: "Overview"
|
||||||
|
case .windowControls: "Window Controls"
|
||||||
|
case .secondaryWindow: "Secondary Window"
|
||||||
|
case .dialogs: "Dialogs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var systemImage: String {
|
||||||
|
switch self {
|
||||||
|
case .overview: "macwindow"
|
||||||
|
case .windowControls: "slider.horizontal.3"
|
||||||
|
case .secondaryWindow: "uiwindow.split.2x1"
|
||||||
|
case .dialogs: "square.and.pencil"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct FeatureCard: View {
|
struct FeatureCard: View {
|
||||||
let title: String
|
let title: String
|
||||||
let systemImage: String
|
let systemImage: String
|
||||||
@ -22,49 +49,122 @@ struct FeatureCard: View {
|
|||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@Environment(\.openWindow) private var openWindow
|
@Environment(\.openWindow) private var openWindow
|
||||||
|
|
||||||
|
@State private var selection: DemoSection? = .overview
|
||||||
@State private var documentTitle = "Swift Window Demo"
|
@State private var documentTitle = "Swift Window Demo"
|
||||||
@State private var width: Double = 980
|
@State private var width: Double = 980
|
||||||
@State private var height: Double = 640
|
@State private var height: Double = 640
|
||||||
|
@State private var windowOpacity: Double = 1.0
|
||||||
@State private var showSheet = false
|
@State private var showSheet = false
|
||||||
@State private var showDialog = false
|
@State private var showDialog = false
|
||||||
|
@State private var showAlert = false
|
||||||
|
@State private var statusMessage = "Ready"
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationSplitView {
|
NavigationSplitView {
|
||||||
List {
|
List(DemoSection.allCases, selection: $selection) { section in
|
||||||
Label("Overview", systemImage: "macwindow")
|
Label(section.title, systemImage: section.systemImage)
|
||||||
Label("Window Controls", systemImage: "slider.horizontal.3")
|
.tag(section)
|
||||||
Label("Secondary Window", systemImage: "uiwindow.split.2x1")
|
|
||||||
Label("Dialogs", systemImage: "square.and.pencil")
|
|
||||||
}
|
}
|
||||||
.navigationTitle("Capabilities")
|
.navigationTitle("Capabilities")
|
||||||
.listStyle(.sidebar)
|
.listStyle(.sidebar)
|
||||||
} detail: {
|
} detail: {
|
||||||
|
Group {
|
||||||
|
switch selection ?? .overview {
|
||||||
|
case .overview:
|
||||||
|
overviewView
|
||||||
|
case .windowControls:
|
||||||
|
windowControlsView
|
||||||
|
case .secondaryWindow:
|
||||||
|
secondaryWindowView
|
||||||
|
case .dialogs:
|
||||||
|
dialogsView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle((selection ?? .overview).title)
|
||||||
|
.sheet(isPresented: $showSheet) {
|
||||||
|
SheetDemoView(statusMessage: $statusMessage)
|
||||||
|
}
|
||||||
|
.alert("Demo alert", isPresented: $showAlert) {
|
||||||
|
Button("OK") {
|
||||||
|
statusMessage = "Alert acknowledged"
|
||||||
|
}
|
||||||
|
} message: {
|
||||||
|
Text("This is a standard alert attached to the app session.")
|
||||||
|
}
|
||||||
|
.confirmationDialog("Test confirmation dialog", isPresented: $showDialog, titleVisibility: .visible) {
|
||||||
|
Button("Center Main Window") {
|
||||||
|
WindowCommandCenter.centerMainWindow()
|
||||||
|
statusMessage = "Centered the main window"
|
||||||
|
}
|
||||||
|
Button("Open Utility Window") {
|
||||||
|
openWindow(id: "inspector")
|
||||||
|
statusMessage = "Opened the utility window"
|
||||||
|
}
|
||||||
|
Button("Cancel", role: .cancel) {
|
||||||
|
statusMessage = "Confirmation cancelled"
|
||||||
|
}
|
||||||
|
} message: {
|
||||||
|
Text("Choose an action to prove the dialog actually triggers app behavior.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var overviewView: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 22) {
|
VStack(alignment: .leading, spacing: 22) {
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
Text("Main Window Demo")
|
Text("Main Window Demo")
|
||||||
.font(.system(size: 34, weight: .bold))
|
.font(.system(size: 34, weight: .bold))
|
||||||
Text("A current-style SwiftUI macOS app that exercises real desktop window behaviors instead of just rendering a static view.")
|
Text("A functional SwiftUI macOS app that demonstrates real window controls, dialogs, multi-window behavior, and tray integration.")
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid(horizontalSpacing: 16, verticalSpacing: 16) {
|
Grid(horizontalSpacing: 16, verticalSpacing: 16) {
|
||||||
GridRow {
|
GridRow {
|
||||||
FeatureCard(title: "Resizable", systemImage: "arrow.up.left.and.arrow.down.right", detail: "Set a target content size and apply it to the frontmost app window.")
|
FeatureCard(title: "Resizable Window", systemImage: "arrow.up.left.and.arrow.down.right", detail: "Resize, center, retitle, and fade the main window using live controls.")
|
||||||
FeatureCard(title: "Secondary Window", systemImage: "macwindow.on.rectangle", detail: "Open a separate utility-style scene to prove multi-window support.")
|
FeatureCard(title: "Working Sidebar", systemImage: "sidebar.left", detail: "Each sidebar section now drives a different detail view instead of being static decoration.")
|
||||||
}
|
}
|
||||||
GridRow {
|
GridRow {
|
||||||
FeatureCard(title: "Sheet + Dialog", systemImage: "rectangle.portrait.and.arrow.right", detail: "Trigger standard macOS sheets and confirmation dialogs.")
|
FeatureCard(title: "Dialogs + Alerts", systemImage: "rectangle.portrait.and.arrow.right", detail: "Open a sheet, alert, and confirmation dialog that each perform visible actions.")
|
||||||
FeatureCard(title: "Tray Integration", systemImage: "menubar.rectangle", detail: "Use the menu-bar item to reopen the main window at any time.")
|
FeatureCard(title: "Tray Menu", systemImage: "menubar.rectangle", detail: "Tray items are explicitly enabled and can reopen or center the main window.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupBox("Window controls") {
|
GroupBox("Quick actions") {
|
||||||
VStack(alignment: .leading, spacing: 14) {
|
HStack(spacing: 12) {
|
||||||
|
Button("Center Window") {
|
||||||
|
WindowCommandCenter.centerMainWindow()
|
||||||
|
statusMessage = "Centered main window"
|
||||||
|
}
|
||||||
|
Button("Open Utility Window") {
|
||||||
|
openWindow(id: "inspector")
|
||||||
|
statusMessage = "Opened utility window"
|
||||||
|
}
|
||||||
|
Button("Show Sheet") {
|
||||||
|
showSheet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
Label(statusMessage, systemImage: "checkmark.circle")
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
.padding(24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var windowControlsView: some View {
|
||||||
|
Form {
|
||||||
|
Section("Window identity") {
|
||||||
TextField("Window title", text: $documentTitle)
|
TextField("Window title", text: $documentTitle)
|
||||||
.textFieldStyle(.roundedBorder)
|
Button("Apply Title") {
|
||||||
|
WindowCommandCenter.renameMainWindow(to: documentTitle)
|
||||||
|
statusMessage = "Renamed main window"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HStack {
|
Section("Window size") {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("Width: \(Int(width))")
|
Text("Width: \(Int(width))")
|
||||||
Slider(value: $width, in: 700...1400, step: 10)
|
Slider(value: $width, in: 700...1400, step: 10)
|
||||||
@ -73,52 +173,103 @@ struct ContentView: View {
|
|||||||
Text("Height: \(Int(height))")
|
Text("Height: \(Int(height))")
|
||||||
Slider(value: $height, in: 480...960, step: 10)
|
Slider(value: $height, in: 480...960, step: 10)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Button("Apply Size") {
|
Button("Apply Size") {
|
||||||
WindowCommandCenter.resizeMainWindow(width: width, height: height)
|
WindowCommandCenter.resizeMainWindow(width: width, height: height)
|
||||||
|
statusMessage = "Resized main window"
|
||||||
}
|
}
|
||||||
Button("Center Window") {
|
Button("Center") {
|
||||||
WindowCommandCenter.centerMainWindow()
|
WindowCommandCenter.centerMainWindow()
|
||||||
|
statusMessage = "Centered main window"
|
||||||
}
|
}
|
||||||
Button("Toggle Full Screen") {
|
Button("Toggle Full Screen") {
|
||||||
WindowCommandCenter.toggleFullScreen()
|
WindowCommandCenter.toggleFullScreen()
|
||||||
|
statusMessage = "Toggled full screen"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, 4)
|
|
||||||
|
Section("Window appearance") {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("Opacity: \(windowOpacity.formatted(.number.precision(.fractionLength(2))))")
|
||||||
|
Slider(value: $windowOpacity, in: 0.35...1.0, step: 0.05)
|
||||||
}
|
}
|
||||||
|
Button("Apply Opacity") {
|
||||||
|
WindowCommandCenter.setMainWindowAlpha(windowOpacity)
|
||||||
|
statusMessage = "Adjusted window opacity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.padding(24)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var secondaryWindowView: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 18) {
|
||||||
|
Text("Secondary Window Demo")
|
||||||
|
.font(.largeTitle.bold())
|
||||||
|
Text("Use this section to prove the app can open and focus a second real window, which is useful for inspectors, logs, tools, or floating utilities.")
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Button("Open Utility Window") {
|
Button("Open Utility Window") {
|
||||||
openWindow(id: "inspector")
|
openWindow(id: "inspector")
|
||||||
|
statusMessage = "Opened utility window"
|
||||||
}
|
}
|
||||||
|
Button("Bring Main Window Forward") {
|
||||||
|
WindowCommandCenter.showMainWindow()
|
||||||
|
statusMessage = "Brought main window forward"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBox("What this demonstrates") {
|
||||||
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
|
Label("Multiple scenes/windows", systemImage: "macwindow.on.rectangle")
|
||||||
|
Label("Window switching from app UI", systemImage: "arrow.triangle.2.circlepath")
|
||||||
|
Label("Useful split between content and tools", systemImage: "sidebar.right")
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.top, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(24)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dialogsView: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 18) {
|
||||||
|
Text("Dialogs Demo")
|
||||||
|
.font(.largeTitle.bold())
|
||||||
|
Text("These controls trigger different interaction patterns so the app demonstrates more than a static window.")
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
|
||||||
|
HStack(spacing: 12) {
|
||||||
Button("Show Sheet") {
|
Button("Show Sheet") {
|
||||||
showSheet = true
|
showSheet = true
|
||||||
}
|
}
|
||||||
|
Button("Show Alert") {
|
||||||
|
showAlert = true
|
||||||
|
}
|
||||||
Button("Show Confirmation") {
|
Button("Show Confirmation") {
|
||||||
showDialog = true
|
showDialog = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroupBox("Last action") {
|
||||||
|
Text(statusMessage)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.top, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(24)
|
.padding(24)
|
||||||
}
|
}
|
||||||
.navigationTitle(documentTitle)
|
|
||||||
.sheet(isPresented: $showSheet) {
|
|
||||||
SheetDemoView()
|
|
||||||
}
|
|
||||||
.confirmationDialog("Test confirmation dialog", isPresented: $showDialog, titleVisibility: .visible) {
|
|
||||||
Button("Acknowledge") {}
|
|
||||||
Button("Cancel", role: .cancel) {}
|
|
||||||
} message: {
|
|
||||||
Text("This validates standard app-window attached dialogs on macOS.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SheetDemoView: View {
|
struct SheetDemoView: View {
|
||||||
|
@Binding var statusMessage: String
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@ -129,7 +280,10 @@ struct SheetDemoView: View {
|
|||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Button("Close") { dismiss() }
|
Button("Close") {
|
||||||
|
statusMessage = "Closed attached sheet"
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
.keyboardShortcut(.defaultAction)
|
.keyboardShortcut(.defaultAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ enum WindowCommandCenter {
|
|||||||
var frame = window.frame
|
var frame = window.frame
|
||||||
frame.size = NSSize(width: width, height: height)
|
frame.size = NSSize(width: width, height: height)
|
||||||
window.setFrame(frame, display: true, animate: true)
|
window.setFrame(frame, display: true, animate: true)
|
||||||
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
window.makeKeyAndOrderFront(nil)
|
window.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +34,18 @@ enum WindowCommandCenter {
|
|||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
window.makeKeyAndOrderFront(nil)
|
window.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func renameMainWindow(to title: String) {
|
||||||
|
guard let window = mainWindow() else { return }
|
||||||
|
window.title = title
|
||||||
|
}
|
||||||
|
|
||||||
|
static func setMainWindowAlpha(_ value: Double) {
|
||||||
|
guard let window = mainWindow() else { return }
|
||||||
|
window.alphaValue = CGFloat(value)
|
||||||
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
|
window.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class WindowAccessor: NSView {
|
final class WindowAccessor: NSView {
|
||||||
@ -65,45 +78,6 @@ struct MainWindowConfigurator: NSViewRepresentable {
|
|||||||
func updateNSView(_ nsView: NSView, context: Context) {}
|
func updateNSView(_ nsView: NSView, context: Context) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class TrayController: NSObject {
|
|
||||||
private var statusItem: NSStatusItem?
|
|
||||||
|
|
||||||
func install() {
|
|
||||||
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
|
||||||
item.button?.image = NSImage(systemSymbolName: "menubar.rectangle", accessibilityDescription: "Swift Window Demo")
|
|
||||||
item.button?.toolTip = "Swift Window Demo"
|
|
||||||
|
|
||||||
let menu = NSMenu()
|
|
||||||
|
|
||||||
let openItem = NSMenuItem(title: "Open Main Window", action: #selector(MenuActionBox.performAction), keyEquivalent: "o")
|
|
||||||
openItem.target = MenuActionBox {
|
|
||||||
WindowCommandCenter.showMainWindow()
|
|
||||||
}
|
|
||||||
menu.addItem(openItem)
|
|
||||||
|
|
||||||
let centerItem = NSMenuItem(title: "Center Main Window", action: #selector(MenuActionBox.performAction), keyEquivalent: "c")
|
|
||||||
centerItem.target = MenuActionBox {
|
|
||||||
WindowCommandCenter.centerMainWindow()
|
|
||||||
}
|
|
||||||
menu.addItem(centerItem)
|
|
||||||
|
|
||||||
menu.addItem(.separator())
|
|
||||||
|
|
||||||
let quitItem = NSMenuItem(title: "Quit", action: #selector(MenuActionBox.performAction), keyEquivalent: "q")
|
|
||||||
quitItem.target = MenuActionBox {
|
|
||||||
NSApp.terminate(nil)
|
|
||||||
}
|
|
||||||
menu.addItem(quitItem)
|
|
||||||
|
|
||||||
objc_setAssociatedObject(openItem, UnsafeRawPointer(bitPattern: 1)!, openItem.target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
||||||
objc_setAssociatedObject(centerItem, UnsafeRawPointer(bitPattern: 2)!, centerItem.target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
||||||
objc_setAssociatedObject(quitItem, UnsafeRawPointer(bitPattern: 3)!, quitItem.target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
||||||
|
|
||||||
item.menu = menu
|
|
||||||
statusItem = item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class MenuActionBox: NSObject {
|
final class MenuActionBox: NSObject {
|
||||||
private let action: () -> Void
|
private let action: () -> Void
|
||||||
|
|
||||||
@ -116,6 +90,58 @@ final class MenuActionBox: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class TrayController: NSObject {
|
||||||
|
private var statusItem: NSStatusItem?
|
||||||
|
private var retainedTargets: [MenuActionBox] = []
|
||||||
|
|
||||||
|
func install() {
|
||||||
|
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||||
|
item.button?.image = NSImage(systemSymbolName: "menubar.rectangle", accessibilityDescription: "Swift Window Demo")
|
||||||
|
item.button?.toolTip = "Swift Window Demo"
|
||||||
|
|
||||||
|
let menu = NSMenu()
|
||||||
|
menu.autoenablesItems = false
|
||||||
|
|
||||||
|
let openTarget = MenuActionBox {
|
||||||
|
WindowCommandCenter.showMainWindow()
|
||||||
|
}
|
||||||
|
let openItem = NSMenuItem(title: "Open Main Window", action: #selector(MenuActionBox.performAction), keyEquivalent: "o")
|
||||||
|
openItem.target = openTarget
|
||||||
|
openItem.isEnabled = true
|
||||||
|
menu.addItem(openItem)
|
||||||
|
|
||||||
|
let centerTarget = MenuActionBox {
|
||||||
|
WindowCommandCenter.centerMainWindow()
|
||||||
|
}
|
||||||
|
let centerItem = NSMenuItem(title: "Center Main Window", action: #selector(MenuActionBox.performAction), keyEquivalent: "c")
|
||||||
|
centerItem.target = centerTarget
|
||||||
|
centerItem.isEnabled = true
|
||||||
|
menu.addItem(centerItem)
|
||||||
|
|
||||||
|
let fullscreenTarget = MenuActionBox {
|
||||||
|
WindowCommandCenter.toggleFullScreen()
|
||||||
|
}
|
||||||
|
let fullscreenItem = NSMenuItem(title: "Toggle Full Screen", action: #selector(MenuActionBox.performAction), keyEquivalent: "f")
|
||||||
|
fullscreenItem.target = fullscreenTarget
|
||||||
|
fullscreenItem.isEnabled = true
|
||||||
|
menu.addItem(fullscreenItem)
|
||||||
|
|
||||||
|
menu.addItem(.separator())
|
||||||
|
|
||||||
|
let quitTarget = MenuActionBox {
|
||||||
|
NSApp.terminate(nil)
|
||||||
|
}
|
||||||
|
let quitItem = NSMenuItem(title: "Quit", action: #selector(MenuActionBox.performAction), keyEquivalent: "q")
|
||||||
|
quitItem.target = quitTarget
|
||||||
|
quitItem.isEnabled = true
|
||||||
|
menu.addItem(quitItem)
|
||||||
|
|
||||||
|
retainedTargets = [openTarget, centerTarget, fullscreenTarget, quitTarget]
|
||||||
|
item.menu = menu
|
||||||
|
statusItem = item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class AppDelegate: NSObject, NSApplicationDelegate {
|
final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
private let trayController = TrayController()
|
private let trayController = TrayController()
|
||||||
|
|
||||||
@ -134,6 +160,7 @@ struct InspectorView: View {
|
|||||||
Divider()
|
Divider()
|
||||||
Label("Independent scene", systemImage: "macwindow.on.rectangle")
|
Label("Independent scene", systemImage: "macwindow.on.rectangle")
|
||||||
Label("Useful for inspectors, logs, or tools", systemImage: "sidebar.right")
|
Label("Useful for inspectors, logs, or tools", systemImage: "sidebar.right")
|
||||||
|
Label("Opened from both sidebar actions and tray-driven workflows", systemImage: "menubar.rectangle")
|
||||||
}
|
}
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.frame(minWidth: 360, minHeight: 220)
|
.frame(minWidth: 360, minHeight: 220)
|
||||||
@ -156,6 +183,11 @@ struct SwiftTrayDemoApp: App {
|
|||||||
WindowCommandCenter.centerMainWindow()
|
WindowCommandCenter.centerMainWindow()
|
||||||
}
|
}
|
||||||
.keyboardShortcut("0")
|
.keyboardShortcut("0")
|
||||||
|
|
||||||
|
Button("Toggle Full Screen") {
|
||||||
|
WindowCommandCenter.toggleFullScreen()
|
||||||
|
}
|
||||||
|
.keyboardShortcut("f")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user