mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Better keyboard shortcuts
* Override `window.sendEvent` to implement global [space] play/pause * Add Controls menu to implement stop, prev, next as ⌘., ⌘← and ⌘→
This commit is contained in:
parent
34f941017f
commit
46dcd60ed1
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -176,6 +176,34 @@
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Controls" id="hB8-hX-gD5">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Controls" autoenablesItems="NO" id="61K-cL-XWL">
|
||||
<items>
|
||||
<menuItem title="Play" keyEquivalent=" " id="xXJ-ld-Y8C">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="playPauseMenuAction:" target="Voe-Tx-rLC" id="Rld-sw-gZY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop" keyEquivalent="." id="gWV-jG-Mxw">
|
||||
<connections>
|
||||
<action selector="stopMenuAction:" target="Voe-Tx-rLC" id="Bz3-r5-4bf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Next song" keyEquivalent="" id="NXq-Bk-4E0">
|
||||
<connections>
|
||||
<action selector="nextTrackMenuAction:" target="Voe-Tx-rLC" id="uhI-Rf-2WT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Previous song" keyEquivalent="" id="Ziz-Ge-r1Q">
|
||||
<connections>
|
||||
<action selector="prevTrackMenuAction:" target="Voe-Tx-rLC" id="05d-gm-3bo"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
@ -237,8 +265,12 @@
|
||||
<outlet property="connectMenuItem" destination="VlA-Re-OZs" id="Zzt-yq-mtp"/>
|
||||
<outlet property="disconnectMenuItem" destination="yjK-qU-C6d" id="qel-dM-Gbl"/>
|
||||
<outlet property="mainWindowMenuItem" destination="1Sq-L7-znT" id="dC6-yY-6Ss"/>
|
||||
<outlet property="nextSongMenuItem" destination="NXq-Bk-4E0" id="QEA-iy-BPE"/>
|
||||
<outlet property="playPauseMenuItem" destination="xXJ-ld-Y8C" id="aeQ-wi-en7"/>
|
||||
<outlet property="playSelectedSongMenuItem" destination="dyT-9E-DRY" id="UY2-SN-YMF"/>
|
||||
<outlet property="playSelectedSongNextMenuItem" destination="Q8j-jr-IOp" id="Jqh-ia-sMK"/>
|
||||
<outlet property="previousSongMenuItem" destination="Ziz-Ge-r1Q" id="Ufe-w4-alG"/>
|
||||
<outlet property="stopMenuItem" destination="gWV-jG-Mxw" id="AkD-66-iWe"/>
|
||||
<outlet property="updateDatabaseMenuItem" destination="EJg-93-1F6" id="gMf-SQ-lyI"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 }
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user