How to remap macOS default keyboard shortcuts in a SwiftUI native app

152 views Asked by At

I'm building a multiplatform app with SwiftUI for iOS, iPadOS and macOS. The macOS app will be a native app, rather than using Catalyst.

The app has a number of different data types which can be added, the principal of which is an Event type. I want to add these as a submenu in the File menu, with the new event action, the most commonly used, available as ⌘N.

That keyboard shortcut is currently mapped to the New Window built-in menu action. I'd like to keep that action but instead, remap its keyboard shortcut to ⌘⇧N.

I can't see how to do that, however.

Currently I have a command set defined as below (with an environment object that handles the display of, and navigation to, the relevant panels):

struct NewItemCommands: Commands {
    @EnvironmentObject private var appNavigation: AppNavigation

    var body: some Commands {
        CommandGroup(before: .newItem) {
            Menu("New") {
                Button("Event", action: appNavigation.newEvent)
                    .keyboardShortcut("N")
                Button("Genre", action: appNavigation.newGenre)
                Button("Publication", action: appNavigation.newPublication)
                Button("Venue", action: appNavigation.newVenue)
            }
            .disabled(appNavigation.isShowingModal)
        }
    }
}

This gives me the submenu I want, with the correct shortcut assigned to New > Event. However, the New Window's default shortcut remains but never gets responded to:

Example of menu, as modified by the above code

Is there a way to remap that shortcut for New Window - or a way to create a new command with identical functionality that I can use to replace the default, with my own shortcut assigned?

1

There are 1 answers

0
Sweeper On BEST ANSWER

You can use CommandGroup(replacing:) instead of CommandGroup(before:). Pass in .newItem to replace the "new window" menu item, then add your own implementation of it, with keyboardShortcut(...).

.commands {
    CommandGroup(replacing: .newItem) {
        Menu("New") {
            Button("Event", action: {...})
                .keyboardShortcut("N")
            Button("Genre", action: {...})
            Button("Publication", action: {...})
            Button("Venue", action: {...})
        }
        Button("New Window") {
            // get this with @Environment(\.openWindow) var openWindow
            // and give your WindowGroup some id
            openWindow(id: "Some ID")
        }.keyboardShortcut("N", modifiers: [.command, .shift])
    }
}