mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Double click on a track to play it
This commit is contained in:
parent
998ddb60bc
commit
338dde08d3
@ -61,6 +61,21 @@ class AlbumDetailView: NSViewController {
|
||||
albumCoverView.image = .defaultCoverArt
|
||||
}
|
||||
|
||||
@IBAction func playAlbum(_ sender: NSButton) {
|
||||
guard let album = album else { return }
|
||||
|
||||
App.store.dispatch(MPDPlayAlbum(album: album.mpdAlbum))
|
||||
}
|
||||
|
||||
@IBAction func playSong(_ sender: AlbumDetailSongListView) {
|
||||
guard let song = dataSource.albumSongs[sender.selectedRow].song
|
||||
else { return }
|
||||
|
||||
let queueLength = App.store.state.queueState.queue.count
|
||||
App.store.dispatch(MPDAppendTrack(song: song.mpdSong))
|
||||
App.store.dispatch(MPDPlayTrack(queuePos: queueLength))
|
||||
}
|
||||
|
||||
func getAlbumSongs(for album: Album) {
|
||||
App.mpdClient.getAlbumSongs(for: album.mpdAlbum) { [weak self] (mpdSongs: [MPDClient.MPDSong]) in
|
||||
self?.dataSource.setAlbumSongs(
|
||||
@ -135,6 +150,10 @@ extension AlbumDetailView: NSTableViewDelegate {
|
||||
return view
|
||||
}
|
||||
|
||||
func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
|
||||
return dataSource.albumSongs[row].disc == nil
|
||||
}
|
||||
|
||||
func cellForDiscNumber(_ tableView: NSTableView, with disc: String) -> NSView {
|
||||
let cellView = tableView.makeView(
|
||||
withIdentifier: .discNumber,
|
||||
|
||||
@ -58,12 +58,6 @@ class AlbumViewItem: NSCollectionViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func playAlbum(_ sender: NSButton) {
|
||||
guard let album = album else { return }
|
||||
|
||||
App.store.dispatch(MPDPlayAlbum(album: album.mpdAlbum))
|
||||
}
|
||||
|
||||
@IBAction func showAlbumDetail(_ sender: NSButton) {
|
||||
guard let album = album else { return }
|
||||
|
||||
|
||||
@ -58,6 +58,10 @@ extension MPDClient {
|
||||
guard let songs = userData["songs"] as? [MPDSong]
|
||||
else { return }
|
||||
sendReplaceQueue(songs)
|
||||
case .appendSong:
|
||||
guard let song = userData["song"] as? MPDSong
|
||||
else { return }
|
||||
sendAppendSong(song)
|
||||
|
||||
// Album commands
|
||||
case .fetchAllAlbums:
|
||||
|
||||
@ -18,6 +18,10 @@ extension MPDClient {
|
||||
enqueueCommand(command: .playTrack, userData: ["queuePos": queuePos])
|
||||
}
|
||||
|
||||
func appendSong(_ song: MPDSong) {
|
||||
enqueueCommand(command: .appendSong, userData: ["song": song])
|
||||
}
|
||||
|
||||
func sendPlayTrack(at queuePos: Int) {
|
||||
mpd_run_play_pos(self.connection, UInt32(queuePos))
|
||||
}
|
||||
@ -40,4 +44,8 @@ extension MPDClient {
|
||||
}
|
||||
mpd_run_play_pos(self.connection, 0)
|
||||
}
|
||||
|
||||
func sendAppendSong(_ song: MPDSong) {
|
||||
mpd_run_add(self.connection, song.uri)
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ extension MPDClient {
|
||||
case fetchQueue
|
||||
case playTrack
|
||||
case replaceQueue
|
||||
case appendSong
|
||||
|
||||
// Album commands
|
||||
case fetchAllAlbums
|
||||
|
||||
@ -59,6 +59,9 @@
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="playAlbum:" target="-2" id="LTw-Lg-yH2"/>
|
||||
</connections>
|
||||
</button>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BOb-Lr-10M">
|
||||
<rect key="frame" x="359" y="33" width="444" height="418"/>
|
||||
@ -209,6 +212,9 @@
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<action trigger="doubleAction" selector="playSong:" target="-2" id="HmG-Nf-n4c"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<nil key="backgroundColor"/>
|
||||
|
||||
@ -51,20 +51,6 @@
|
||||
<action selector="showAlbumDetail:" target="-2" id="nO1-4H-LHS"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="n8W-do-HyG">
|
||||
<rect key="frame" x="43" y="81" width="42" height="43"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="42" id="XXC-YE-Ego"/>
|
||||
<constraint firstAttribute="width" constant="42" id="zcR-GT-zym"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="inline" bezelStyle="inline" image="playButtonLarge" imagePosition="only" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="T1p-LZ-RpJ">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="playAlbum:" target="-2" id="gNt-Rn-kte"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="x5e-56-uVO" firstAttribute="leading" secondItem="Kfb-8f-ean" secondAttribute="leading" id="1Hi-Uk-rkL"/>
|
||||
@ -73,7 +59,6 @@
|
||||
<constraint firstItem="x5e-56-uVO" firstAttribute="trailing" secondItem="Kfb-8f-ean" secondAttribute="trailing" id="BYd-Fg-DVb"/>
|
||||
<constraint firstItem="Kfb-8f-ean" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="JMi-4i-dgs"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Kfb-8f-ean" secondAttribute="trailing" id="KQC-Wz-Bsg"/>
|
||||
<constraint firstItem="n8W-do-HyG" firstAttribute="centerX" secondItem="Kfb-8f-ean" secondAttribute="centerX" id="Kf1-ws-d4q"/>
|
||||
<constraint firstItem="5Uu-j1-qyT" firstAttribute="leading" secondItem="KEh-NL-c2W" secondAttribute="leading" id="MUo-0i-fX9"/>
|
||||
<constraint firstItem="Kfb-8f-ean" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="Qbk-jx-zAi"/>
|
||||
<constraint firstItem="KEh-NL-c2W" firstAttribute="trailing" secondItem="Kfb-8f-ean" secondAttribute="trailing" id="U0w-G4-ggX"/>
|
||||
@ -81,12 +66,10 @@
|
||||
<constraint firstAttribute="bottom" secondItem="5Uu-j1-qyT" secondAttribute="bottom" id="gci-4h-pDZ"/>
|
||||
<constraint firstItem="x5e-56-uVO" firstAttribute="top" secondItem="Kfb-8f-ean" secondAttribute="top" id="hw2-ik-6VW"/>
|
||||
<constraint firstItem="x5e-56-uVO" firstAttribute="bottom" secondItem="Kfb-8f-ean" secondAttribute="bottom" id="iVQ-Vn-dSV"/>
|
||||
<constraint firstItem="n8W-do-HyG" firstAttribute="centerY" secondItem="Kfb-8f-ean" secondAttribute="centerY" id="pgP-oA-Nxa"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Kfb-8f-ean" secondAttribute="bottom" constant="39" id="sid-zJ-YMA"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="Kfb-8f-ean" id="T7Z-En-dU3"/>
|
||||
<outlet property="playButton" destination="n8W-do-HyG" id="Xw0-iI-svx"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-22" y="125.5"/>
|
||||
</customView>
|
||||
@ -94,6 +77,5 @@
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="defaultCoverArt" width="128" height="128"/>
|
||||
<image name="playButtonLarge" width="22" height="22"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@ -16,6 +16,10 @@ struct MPDStopAction: Action {}
|
||||
struct MPDNextTrackAction: Action {}
|
||||
struct MPDPrevTrackAction: Action {}
|
||||
|
||||
struct MPDAppendTrack: Action {
|
||||
let song: MPDClient.MPDSong
|
||||
}
|
||||
|
||||
struct MPDPlayTrack: Action {
|
||||
let queuePos: Int
|
||||
}
|
||||
|
||||
@ -30,6 +30,9 @@ func mpdReducer(action: Action, state: MPDState?) -> MPDState {
|
||||
case is MPDPrevTrackAction:
|
||||
App.mpdClient.prevTrack()
|
||||
|
||||
case let action as MPDAppendTrack:
|
||||
App.mpdClient.appendSong(action.song)
|
||||
|
||||
case let action as MPDPlayTrack:
|
||||
App.mpdClient.playTrack(at: action.queuePos)
|
||||
|
||||
|
||||
@ -9,80 +9,9 @@
|
||||
import AppKit
|
||||
|
||||
class AlbumItemView: NSView {
|
||||
var trackingArea: NSTrackingArea?
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
super.updateTrackingAreas()
|
||||
|
||||
guard let albumImageView = imageView else { return }
|
||||
|
||||
if let trackingArea = self.trackingArea {
|
||||
self.removeTrackingArea(trackingArea)
|
||||
}
|
||||
|
||||
let trackingArea = NSTrackingArea(
|
||||
rect: albumImageView.frame,
|
||||
options: [.mouseEnteredAndExited, .activeAlways],
|
||||
owner: self,
|
||||
userInfo: nil
|
||||
)
|
||||
|
||||
self.trackingArea = trackingArea
|
||||
addTrackingArea(trackingArea)
|
||||
}
|
||||
|
||||
required init?(coder decoder: NSCoder) {
|
||||
super.init(coder: decoder)
|
||||
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(viewWillScroll(_:)),
|
||||
name: NSScrollView.willStartLiveScrollNotification,
|
||||
object: nil
|
||||
)
|
||||
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(viewDidScroll(_:)),
|
||||
name: NSScrollView.didLiveScrollNotification,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
hidePlayButton()
|
||||
}
|
||||
|
||||
@objc func viewWillScroll(_ notification: Notification) {
|
||||
hidePlayButton()
|
||||
}
|
||||
|
||||
@objc func viewDidScroll(_ notification: Notification) {
|
||||
hidePlayButton()
|
||||
}
|
||||
|
||||
override func resize(withOldSuperviewSize oldSize: NSSize) {
|
||||
hidePlayButton()
|
||||
}
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
showPlayButton()
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
hidePlayButton()
|
||||
}
|
||||
|
||||
func showPlayButton() {
|
||||
playButton.isHidden = false
|
||||
}
|
||||
|
||||
func hidePlayButton() {
|
||||
playButton.isHidden = true
|
||||
}
|
||||
|
||||
@IBOutlet var imageView: NSImageView!
|
||||
@IBOutlet var playButton: NSButton!
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user