mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Drag and drop moves tracks in queue
For some reason we're not seeing the insert indicator, and I can't figure out why.
This commit is contained in:
parent
8c385d9c88
commit
aef5b8534b
@ -112,6 +112,7 @@
|
|||||||
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BC12275EE410075461B /* AlbumListActions.swift */; };
|
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BC12275EE410075461B /* AlbumListActions.swift */; };
|
||||||
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */; };
|
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */; };
|
||||||
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53D22349002009A20F3 /* MPDIdle.swift */; };
|
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53D22349002009A20F3 /* MPDIdle.swift */; };
|
||||||
|
E4D3BFA622B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4D3BFA522B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift */; };
|
||||||
E4E7A6AD22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E7A6AC22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift */; };
|
E4E7A6AD22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E7A6AC22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift */; };
|
||||||
E4E8CC902204EC7F0024217A /* Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E8CC8F2204EC7F0024217A /* Delegate.swift */; };
|
E4E8CC902204EC7F0024217A /* Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E8CC8F2204EC7F0024217A /* Delegate.swift */; };
|
||||||
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E8CC912204F4B80024217A /* QueueViewController.swift */; };
|
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E8CC912204F4B80024217A /* QueueViewController.swift */; };
|
||||||
@ -317,6 +318,7 @@
|
|||||||
E4B11BC12275EE410075461B /* AlbumListActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumListActions.swift; sourceTree = "<group>"; };
|
E4B11BC12275EE410075461B /* AlbumListActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumListActions.swift; sourceTree = "<group>"; };
|
||||||
E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
||||||
E4C8B53D22349002009A20F3 /* MPDIdle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDIdle.swift; sourceTree = "<group>"; };
|
E4C8B53D22349002009A20F3 /* MPDIdle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDIdle.swift; sourceTree = "<group>"; };
|
||||||
|
E4D3BFA522B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "QueueViewController+NSOutlineViewDelegate.swift"; sourceTree = "<group>"; };
|
||||||
E4E7A6AC22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlbumDetailView+NSTableViewDelegate.swift"; sourceTree = "<group>"; };
|
E4E7A6AC22AAAF98006D566C /* AlbumDetailView+NSTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlbumDetailView+NSTableViewDelegate.swift"; sourceTree = "<group>"; };
|
||||||
E4E8CC8F2204EC7F0024217A /* Delegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Delegate.swift; sourceTree = "<group>"; };
|
E4E8CC8F2204EC7F0024217A /* Delegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Delegate.swift; sourceTree = "<group>"; };
|
||||||
E4E8CC912204F4B80024217A /* QueueViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueViewController.swift; sourceTree = "<group>"; };
|
E4E8CC912204F4B80024217A /* QueueViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueViewController.swift; sourceTree = "<group>"; };
|
||||||
@ -694,6 +696,7 @@
|
|||||||
E47E2FD022205C4600F747E6 /* MainSplitViewController.swift */,
|
E47E2FD022205C4600F747E6 /* MainSplitViewController.swift */,
|
||||||
E4405191227644340090CD6F /* MPDServerController.swift */,
|
E4405191227644340090CD6F /* MPDServerController.swift */,
|
||||||
E4E8CC912204F4B80024217A /* QueueViewController.swift */,
|
E4E8CC912204F4B80024217A /* QueueViewController.swift */,
|
||||||
|
E4D3BFA522B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift */,
|
||||||
E4B11BB52275374B0075461B /* UserNotificationsController.swift */,
|
E4B11BB52275374B0075461B /* UserNotificationsController.swift */,
|
||||||
E465049921E94DF500A70F4C /* WindowController.swift */,
|
E465049921E94DF500A70F4C /* WindowController.swift */,
|
||||||
);
|
);
|
||||||
@ -921,6 +924,7 @@
|
|||||||
E4B11BB62275374B0075461B /* UserNotificationsController.swift in Sources */,
|
E4B11BB62275374B0075461B /* UserNotificationsController.swift in Sources */,
|
||||||
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
||||||
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */,
|
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */,
|
||||||
|
E4D3BFA622B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift in Sources */,
|
||||||
E4405196227879960090CD6F /* MPDActions.swift in Sources */,
|
E4405196227879960090CD6F /* MPDActions.swift in Sources */,
|
||||||
E4405192227644340090CD6F /* MPDServerController.swift in Sources */,
|
E4405192227644340090CD6F /* MPDServerController.swift in Sources */,
|
||||||
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */,
|
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */,
|
||||||
|
|||||||
@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// QueueViewController+NSOutlineViewDelegate.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/6/14.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
extension QueueViewController: NSOutlineViewDelegate {
|
||||||
|
func outlineView(
|
||||||
|
_ outlineView: NSOutlineView,
|
||||||
|
selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet
|
||||||
|
) -> IndexSet {
|
||||||
|
if proposedSelectionIndexes.contains(0) {
|
||||||
|
return IndexSet()
|
||||||
|
} else {
|
||||||
|
return proposedSelectionIndexes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
||||||
|
if let queueItem = item as? QueueItem {
|
||||||
|
switch tableColumn?.identifier.rawValue {
|
||||||
|
case "songTitleColumn":
|
||||||
|
return cellForSongTitle(outlineView, with: queueItem)
|
||||||
|
case "songArtistColumn":
|
||||||
|
return cellForSongArtist(outlineView, with: queueItem)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else if tableColumn?.identifier.rawValue == "songTitleColumn" {
|
||||||
|
return cellForQueueHeading(outlineView)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineViewSelectionDidChange(_ notification: Notification) {
|
||||||
|
if queueView.selectedRow >= 1 {
|
||||||
|
let queueItem = dataSource.queue[queueView.selectedRow - 1]
|
||||||
|
|
||||||
|
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: queueItem))
|
||||||
|
} else {
|
||||||
|
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cellForSongTitle(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
|
||||||
|
let cellView = outlineView.makeView(
|
||||||
|
withIdentifier: .queueSongTitle,
|
||||||
|
owner: self
|
||||||
|
) as! QueueSongTitleView
|
||||||
|
|
||||||
|
cellView.setQueueSong(queueItem, queueIcon: dataSource.queueIcon)
|
||||||
|
|
||||||
|
return cellView
|
||||||
|
}
|
||||||
|
|
||||||
|
func cellForSongArtist(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
|
||||||
|
let cellView = outlineView.makeView(
|
||||||
|
withIdentifier: .queueSongArtist,
|
||||||
|
owner: self
|
||||||
|
) as! NSTableCellView
|
||||||
|
|
||||||
|
cellView.textField?.stringValue = queueItem.song.artist
|
||||||
|
if queueItem.isPlaying {
|
||||||
|
cellView.textField?.font = .systemFontBold
|
||||||
|
} else {
|
||||||
|
cellView.textField?.font = .systemFontRegular
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellView
|
||||||
|
}
|
||||||
|
|
||||||
|
func cellForQueueHeading(_ outlineView: NSOutlineView) -> NSView {
|
||||||
|
let cellView = outlineView.makeView(
|
||||||
|
withIdentifier: .queueHeading,
|
||||||
|
owner: self
|
||||||
|
) as! NSTableCellView
|
||||||
|
|
||||||
|
cellView.textField?.stringValue = "QUEUE"
|
||||||
|
|
||||||
|
return cellView
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,8 +9,7 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import ReSwift
|
import ReSwift
|
||||||
|
|
||||||
class QueueViewController: NSViewController,
|
class QueueViewController: NSViewController {
|
||||||
NSOutlineViewDelegate {
|
|
||||||
var dataSource = QueueDataSource()
|
var dataSource = QueueDataSource()
|
||||||
|
|
||||||
@IBOutlet var queueView: NSOutlineView!
|
@IBOutlet var queueView: NSOutlineView!
|
||||||
@ -23,8 +22,10 @@ class QueueViewController: NSViewController,
|
|||||||
$0.select { $0.queueState }
|
$0.select { $0.queueState }
|
||||||
}
|
}
|
||||||
|
|
||||||
queueView.dataSource = dataSource
|
// queueView.dataSource = dataSource
|
||||||
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
||||||
|
queueView.registerForDraggedTypes([REORDER_PASTEBOARD_TYPE])
|
||||||
|
queueView.draggingDestinationFeedbackStyle = .regular
|
||||||
}
|
}
|
||||||
|
|
||||||
override func keyDown(with event: NSEvent) {
|
override func keyDown(with event: NSEvent) {
|
||||||
@ -64,81 +65,31 @@ class QueueViewController: NSViewController,
|
|||||||
App.store.dispatch(MPDRemoveTrack(queuePos: queuePos))
|
App.store.dispatch(MPDRemoveTrack(queuePos: queuePos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func outlineView(
|
extension QueueViewController: NSOutlineViewDataSource {
|
||||||
_ outlineView: NSOutlineView,
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
||||||
selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet
|
return dataSource.outlineView(outlineView, numberOfChildrenOfItem: item)
|
||||||
) -> IndexSet {
|
|
||||||
if proposedSelectionIndexes.contains(0) {
|
|
||||||
return IndexSet()
|
|
||||||
} else {
|
|
||||||
return proposedSelectionIndexes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
||||||
if let queueItem = item as? QueueItem {
|
return dataSource.outlineView(outlineView, isItemExpandable: item)
|
||||||
switch tableColumn?.identifier.rawValue {
|
|
||||||
case "songTitleColumn":
|
|
||||||
return cellForSongTitle(outlineView, with: queueItem)
|
|
||||||
case "songArtistColumn":
|
|
||||||
return cellForSongArtist(outlineView, with: queueItem)
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else if tableColumn?.identifier.rawValue == "songTitleColumn" {
|
|
||||||
return cellForQueueHeading(outlineView)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineViewSelectionDidChange(_ notification: Notification) {
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
||||||
if queueView.selectedRow >= 1 {
|
return dataSource.outlineView(outlineView, child: index, ofItem: item)
|
||||||
let queueItem = dataSource.queue[queueView.selectedRow - 1]
|
|
||||||
|
|
||||||
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: queueItem))
|
|
||||||
} else {
|
|
||||||
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: nil))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cellForSongTitle(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
|
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
|
||||||
let cellView = outlineView.makeView(
|
return dataSource.outlineView(outlineView, pasteboardWriterForItem: item)
|
||||||
withIdentifier: .queueSongTitle,
|
|
||||||
owner: self
|
|
||||||
) as! QueueSongTitleView
|
|
||||||
|
|
||||||
cellView.setQueueSong(queueItem, queueIcon: dataSource.queueIcon)
|
|
||||||
|
|
||||||
return cellView
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cellForSongArtist(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
|
func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
||||||
let cellView = outlineView.makeView(
|
return dataSource.outlineView(outlineView, validateDrop: info, proposedItem: item, proposedChildIndex: index)
|
||||||
withIdentifier: .queueSongArtist,
|
|
||||||
owner: self
|
|
||||||
) as! NSTableCellView
|
|
||||||
|
|
||||||
cellView.textField?.stringValue = queueItem.song.artist
|
|
||||||
if queueItem.isPlaying {
|
|
||||||
cellView.textField?.font = .systemFontBold
|
|
||||||
} else {
|
|
||||||
cellView.textField?.font = .systemFontRegular
|
|
||||||
}
|
|
||||||
|
|
||||||
return cellView
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cellForQueueHeading(_ outlineView: NSOutlineView) -> NSView {
|
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
|
||||||
let cellView = outlineView.makeView(
|
return dataSource.outlineView(outlineView, acceptDrop: info, item: item, childIndex: index)
|
||||||
withIdentifier: .queueHeading,
|
|
||||||
owner: self
|
|
||||||
) as! NSTableCellView
|
|
||||||
|
|
||||||
cellView.textField?.stringValue = "QUEUE"
|
|
||||||
|
|
||||||
return cellView
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
import AppKit
|
import AppKit
|
||||||
|
|
||||||
|
let REORDER_PASTEBOARD_TYPE = NSPasteboard.PasteboardType("me.danbarber.persephone")
|
||||||
|
|
||||||
class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
||||||
var queue: [QueueItem] = []
|
var queue: [QueueItem] = []
|
||||||
var queueIcon: NSImage? = nil
|
var queueIcon: NSImage? = nil
|
||||||
@ -35,7 +37,43 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
if index > 0 {
|
if index > 0 {
|
||||||
return queue[index - 1]
|
return queue[index - 1]
|
||||||
} else {
|
} else {
|
||||||
return false
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
|
||||||
|
guard let queueItem = item as? QueueItem
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
|
let pbItem = NSPasteboardItem()
|
||||||
|
|
||||||
|
pbItem.setPropertyList(["queuePos": queueItem.queuePos], forType: REORDER_PASTEBOARD_TYPE)
|
||||||
|
|
||||||
|
return pbItem
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
||||||
|
guard let draggingTypes = info.draggingPasteboard.types,
|
||||||
|
draggingTypes.contains(REORDER_PASTEBOARD_TYPE),
|
||||||
|
index >= 0
|
||||||
|
else { return [] }
|
||||||
|
|
||||||
|
return .move
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
|
||||||
|
var newQueuePos = index - 1
|
||||||
|
|
||||||
|
guard let payload = info.draggingPasteboard.propertyList(forType: REORDER_PASTEBOARD_TYPE) as? [String: Int],
|
||||||
|
let queuePos = payload["queuePos"]
|
||||||
|
else { return false }
|
||||||
|
|
||||||
|
if newQueuePos > queuePos { newQueuePos -= 1 }
|
||||||
|
|
||||||
|
guard queuePos != newQueuePos else { return false }
|
||||||
|
|
||||||
|
App.store.dispatch(MPDMoveSongInQueue(oldQueuePos: queuePos, newQueuePos: newQueuePos))
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,12 @@ extension MPDClient {
|
|||||||
else { return }
|
else { return }
|
||||||
sendRemoveSong(at: queuePos)
|
sendRemoveSong(at: queuePos)
|
||||||
|
|
||||||
|
case .moveSongInQueue:
|
||||||
|
guard let oldQueuePos = userData["oldQueuePos"] as? Int,
|
||||||
|
let newQueuePos = userData["newQueuePos"] as? Int
|
||||||
|
else { return }
|
||||||
|
sendMoveSongInQueue(at: oldQueuePos, to: newQueuePos)
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case .fetchAllAlbums:
|
case .fetchAllAlbums:
|
||||||
allAlbums()
|
allAlbums()
|
||||||
|
|||||||
@ -30,6 +30,10 @@ extension MPDClient {
|
|||||||
enqueueCommand(command: .removeSong, userData: ["queuePos": queuePos])
|
enqueueCommand(command: .removeSong, userData: ["queuePos": queuePos])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func moveSongInQueue(at queuePos: Int, to newQueuePos: Int) {
|
||||||
|
enqueueCommand(command: .moveSongInQueue, userData: ["oldQueuePos": queuePos, "newQueuePos": newQueuePos])
|
||||||
|
}
|
||||||
|
|
||||||
func sendPlayTrack(at queuePos: Int) {
|
func sendPlayTrack(at queuePos: Int) {
|
||||||
mpd_run_play_pos(self.connection, UInt32(queuePos))
|
mpd_run_play_pos(self.connection, UInt32(queuePos))
|
||||||
}
|
}
|
||||||
@ -64,4 +68,8 @@ extension MPDClient {
|
|||||||
func sendRemoveSong(at queuePos: Int) {
|
func sendRemoveSong(at queuePos: Int) {
|
||||||
mpd_run_delete(self.connection, UInt32(queuePos))
|
mpd_run_delete(self.connection, UInt32(queuePos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendMoveSongInQueue(at oldQueuePos: Int, to newQueuePos: Int) {
|
||||||
|
mpd_run_move(self.connection, UInt32(oldQueuePos), UInt32(newQueuePos))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ extension MPDClient {
|
|||||||
case replaceQueue
|
case replaceQueue
|
||||||
case appendSong
|
case appendSong
|
||||||
case removeSong
|
case removeSong
|
||||||
|
case moveSongInQueue
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case fetchAllAlbums
|
case fetchAllAlbums
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2019 Dan Barber. All rights reserved.
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import AppKit
|
||||||
|
|
||||||
struct QueueItem: Equatable {
|
struct QueueItem: Equatable {
|
||||||
var song: Song
|
var song: Song
|
||||||
|
|||||||
@ -574,7 +574,7 @@
|
|||||||
<scene sceneID="QcX-dC-cTZ">
|
<scene sceneID="QcX-dC-cTZ">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="KIP-rq-4dM" customClass="QueueViewController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController id="KIP-rq-4dM" customClass="QueueViewController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<splitView key="view" wantsLayer="YES" dividerStyle="thin" id="84I-w3-Mxl">
|
<splitView key="view" dividerStyle="thin" id="84I-w3-Mxl">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="328" height="548"/>
|
<rect key="frame" x="0.0" y="0.0" width="328" height="548"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
@ -713,6 +713,7 @@
|
|||||||
</tableColumns>
|
</tableColumns>
|
||||||
<connections>
|
<connections>
|
||||||
<action trigger="doubleAction" selector="playTrack:" target="KIP-rq-4dM" id="opa-6G-OW0"/>
|
<action trigger="doubleAction" selector="playTrack:" target="KIP-rq-4dM" id="opa-6G-OW0"/>
|
||||||
|
<outlet property="dataSource" destination="KIP-rq-4dM" id="AL2-j1-SVE"/>
|
||||||
<outlet property="delegate" destination="KIP-rq-4dM" id="60F-6x-bUE"/>
|
<outlet property="delegate" destination="KIP-rq-4dM" id="60F-6x-bUE"/>
|
||||||
<outlet property="menu" destination="dYA-Jm-eOa" id="9s2-7K-tVx"/>
|
<outlet property="menu" destination="dYA-Jm-eOa" id="9s2-7K-tVx"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
@ -18,6 +18,11 @@ struct MPDPrevTrackAction: Action {}
|
|||||||
|
|
||||||
struct MPDClearQueue: Action {}
|
struct MPDClearQueue: Action {}
|
||||||
|
|
||||||
|
struct MPDMoveSongInQueue: Action {
|
||||||
|
let oldQueuePos: Int
|
||||||
|
let newQueuePos: Int
|
||||||
|
}
|
||||||
|
|
||||||
struct MPDAppendTrack: Action {
|
struct MPDAppendTrack: Action {
|
||||||
let song: MPDClient.MPDSong
|
let song: MPDClient.MPDSong
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,9 @@ func mpdReducer(action: Action, state: MPDState?) -> MPDState {
|
|||||||
case is MPDClearQueue:
|
case is MPDClearQueue:
|
||||||
App.mpdClient.clearQueue()
|
App.mpdClient.clearQueue()
|
||||||
|
|
||||||
|
case let action as MPDMoveSongInQueue:
|
||||||
|
App.mpdClient.moveSongInQueue(at: action.oldQueuePos, to: action.newQueuePos)
|
||||||
|
|
||||||
case let action as MPDAppendTrack:
|
case let action as MPDAppendTrack:
|
||||||
App.mpdClient.appendSong(action.song)
|
App.mpdClient.appendSong(action.song)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user