From 46dcd60ed165a1bc93484198cbd0dc5cc6c91486 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Sat, 7 Mar 2020 17:47:00 -0500 Subject: [PATCH] Better keyboard shortcuts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Override `window.sendEvent` to implement global [space] play/pause * Add Controls menu to implement stop, prev, next as ⌘., ⌘← and ⌘→ --- Persephone/AppDelegate.swift | 31 ++++++++++++++++-- .../Queue/QueueViewController.swift | 12 ------- .../Window/Base.lproj/Main.storyboard | 32 +++++++++++++++++++ .../Window/MainSplitViewController.swift | 8 ----- Persephone/Components/Window/MainWindow.swift | 25 +++++++++++---- .../Components/Window/WindowController.swift | 13 +------- 6 files changed, 80 insertions(+), 41 deletions(-) diff --git a/Persephone/AppDelegate.swift b/Persephone/AppDelegate.swift index bc9d4e9..94da4dc 100644 --- a/Persephone/AppDelegate.swift +++ b/Persephone/AppDelegate.swift @@ -16,6 +16,11 @@ class AppDelegate: NSObject, MediaKeyTapDelegate { var mediaKeyTap: MediaKeyTap? + @IBOutlet weak var playPauseMenuItem: NSMenuItem! + @IBOutlet weak var stopMenuItem: NSMenuItem! + @IBOutlet weak var nextSongMenuItem: NSMenuItem! + @IBOutlet weak var previousSongMenuItem: NSMenuItem! + @IBOutlet weak var connectMenuItem: NSMenuItem! @IBOutlet weak var disconnectMenuItem: NSMenuItem! @IBOutlet weak var mainWindowMenuItem: NSMenuItem! @@ -30,7 +35,7 @@ class AppDelegate: NSObject, App.store.subscribe(self) { $0.select { - ($0.serverState, $0.uiState) + ($0.serverState, $0.playerState, $0.uiState) } } @@ -52,7 +57,11 @@ class AppDelegate: NSObject, if let currentSong = App.store.state.playerState.currentSong, state.isOneOf([.playing, .paused]) { - let nowPlayingItem = NSMenuItem(title: "Now Playing", action: nil, keyEquivalent: "") + let nowPlayingItem = NSMenuItem( + title: state == .playing ? "Now Playing" : "Paused", + action: nil, + keyEquivalent: "" + ) let songItem = NSMenuItem(title: currentSong.title, action: nil, keyEquivalent: "") let albumItem = NSMenuItem( title: "\(currentSong.artist) — \(currentSong.album.title)", @@ -108,6 +117,21 @@ class AppDelegate: NSObject, addSelectedSongToQueueMenuItem.isEnabled = selectedSong != nil } + func setControlsMenuItemsState(state: PlayerState) { + guard let state = state.state else { return } + + playPauseMenuItem.isEnabled = state.isOneOf([.playing, .paused, .stopped]) + stopMenuItem.isEnabled = state.isOneOf([.playing, .paused]) + nextSongMenuItem.isEnabled = state.isOneOf([.playing, .paused]) + previousSongMenuItem.isEnabled = state.isOneOf([.playing, .paused]) + + if state.isOneOf([.paused, .stopped, .unknown]) { + playPauseMenuItem.title = "Play" + } else { + playPauseMenuItem.title = "Pause" + } + } + func setConnectMenuItemsState(connected: Bool) { connectMenuItem.isEnabled = !connected disconnectMenuItem.isEnabled = connected @@ -197,13 +221,14 @@ class AppDelegate: NSObject, extension AppDelegate: StoreSubscriber { typealias StoreSubscriberStateType = ( - serverState: ServerState, uiState: UIState + serverState: ServerState, playerState: PlayerState, uiState: UIState ) func newState(state: StoreSubscriberStateType) { updateDatabaseMenuItem.isEnabled = !state.uiState.databaseUpdating setMainWindowStateMenuItem(state: state.uiState.mainWindowState) setSongMenuItemsState(selectedSong: state.uiState.selectedSong) + setControlsMenuItemsState(state: state.playerState) setConnectMenuItemsState(connected: state.serverState.connected) } } diff --git a/Persephone/Components/Queue/QueueViewController.swift b/Persephone/Components/Queue/QueueViewController.swift index 670fa82..e4338f0 100644 --- a/Persephone/Components/Queue/QueueViewController.swift +++ b/Persephone/Components/Queue/QueueViewController.swift @@ -39,18 +39,6 @@ class QueueViewController: NSViewController { App.store.unsubscribe(self) } - override func keyDown(with event: NSEvent) { - switch event.keyCode { - case NSEvent.keyCodeSpace: - nextResponder?.keyDown(with: event) - case NSEvent.keyCodeBS: - let queuePos = queueView.selectedRow - - App.mpdClient.removeSong(at: queuePos) - default: - super.keyDown(with: event) - } - } @objc func didConnect() { App.mpdClient.fetchQueue() diff --git a/Persephone/Components/Window/Base.lproj/Main.storyboard b/Persephone/Components/Window/Base.lproj/Main.storyboard index e4f41e1..cf2d61f 100644 --- a/Persephone/Components/Window/Base.lproj/Main.storyboard +++ b/Persephone/Components/Window/Base.lproj/Main.storyboard @@ -176,6 +176,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -237,8 +265,12 @@ + + + + diff --git a/Persephone/Components/Window/MainSplitViewController.swift b/Persephone/Components/Window/MainSplitViewController.swift index 4f2aac5..4c8af8b 100644 --- a/Persephone/Components/Window/MainSplitViewController.swift +++ b/Persephone/Components/Window/MainSplitViewController.swift @@ -9,12 +9,4 @@ import AppKit class MainSplitViewController: NSSplitViewController { - override func keyDown(with event: NSEvent) { - switch event.keyCode { - case NSEvent.keyCodeSpace: - nextResponder?.keyDown(with: event) - default: - super.keyDown(with: event) - } - } } diff --git a/Persephone/Components/Window/MainWindow.swift b/Persephone/Components/Window/MainWindow.swift index 397e01d..4b736d0 100644 --- a/Persephone/Components/Window/MainWindow.swift +++ b/Persephone/Components/Window/MainWindow.swift @@ -9,12 +9,25 @@ import AppKit class MainWindow: NSWindow { - override func keyDown(with event: NSEvent) { - switch event.keyCode { - case NSEvent.keyCodeSpace: - nextResponder?.keyDown(with: event) - default: - super.keyDown(with: event) + override func sendEvent(_ event: NSEvent) { + guard let responder = firstResponder else { return } + + if event.type == .keyDown && + doesNotRequireSpace(responder) { + + switch event.keyCode { + case NSEvent.keyCodeSpace: + App.mpdClient.playPause() + default: + super.sendEvent(event) + } + } else { + super.sendEvent(event) } } + + func doesNotRequireSpace(_ responder: NSResponder) -> Bool { + return !responder.isKind(of: NSText.self) && + !responder.isKind(of: NSButton.self) + } } diff --git a/Persephone/Components/Window/WindowController.swift b/Persephone/Components/Window/WindowController.swift index 349cde7..396fae7 100644 --- a/Persephone/Components/Window/WindowController.swift +++ b/Persephone/Components/Window/WindowController.swift @@ -30,7 +30,7 @@ class WindowController: NSWindowController { @IBOutlet var volumeState: NSButton! @IBOutlet weak var searchQuery: NSSearchField! - + override func windowDidLoad() { super.windowDidLoad() window?.titleVisibility = .hidden @@ -51,17 +51,6 @@ class WindowController: NSWindowController { trackRemaining.font = .timerFont } - override func keyDown(with event: NSEvent) { - switch event.keyCode { - case NSEvent.keyCodeSpace: - if !event.isARepeat { - App.mpdClient.playPause() - } - default: - nextResponder?.keyDown(with: event) - } - } - func setTransportControlState(_ state: PlayerState) { guard let state = state.state else { return }