mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Drag album songs onto queue
This commit is contained in:
parent
1bd6edfb33
commit
ba64fed16a
@ -71,6 +71,7 @@
|
|||||||
E47E2FD72220720300F747E6 /* AlbumItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FD62220720300F747E6 /* AlbumItemView.swift */; };
|
E47E2FD72220720300F747E6 /* AlbumItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FD62220720300F747E6 /* AlbumItemView.swift */; };
|
||||||
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FDC2220A6D100F747E6 /* Time.swift */; };
|
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FDC2220A6D100F747E6 /* Time.swift */; };
|
||||||
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */; };
|
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */; };
|
||||||
|
E489E39922B85D0400CA8CBD /* NSPasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E39822B85D0400CA8CBD /* NSPasteboard.swift */; };
|
||||||
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4928E0A2218D62A001D4BEA /* CGColor.swift */; };
|
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4928E0A2218D62A001D4BEA /* CGColor.swift */; };
|
||||||
E4A3A6A122A457B600EA2C40 /* AlbumDetailSongListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */; };
|
E4A3A6A122A457B600EA2C40 /* AlbumDetailSongListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */; };
|
||||||
E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A642D922090CBE00067D21 /* MPDStatus.swift */; };
|
E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A642D922090CBE00067D21 /* MPDStatus.swift */; };
|
||||||
@ -291,6 +292,7 @@
|
|||||||
E47E2FD62220720300F747E6 /* AlbumItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumItemView.swift; sourceTree = "<group>"; };
|
E47E2FD62220720300F747E6 /* AlbumItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumItemView.swift; sourceTree = "<group>"; };
|
||||||
E47E2FDC2220A6D100F747E6 /* Time.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = "<group>"; };
|
E47E2FDC2220A6D100F747E6 /* Time.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = "<group>"; };
|
||||||
E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumViewLayout.swift; sourceTree = "<group>"; };
|
E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumViewLayout.swift; sourceTree = "<group>"; };
|
||||||
|
E489E39822B85D0400CA8CBD /* NSPasteboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSPasteboard.swift; sourceTree = "<group>"; };
|
||||||
E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = "<group>"; };
|
E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = "<group>"; };
|
||||||
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = "<group>"; };
|
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = "<group>"; };
|
||||||
E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = "<group>"; };
|
E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = "<group>"; };
|
||||||
@ -446,6 +448,7 @@
|
|||||||
E435E3E1221CD4E200184CFC /* NSFont.swift */,
|
E435E3E1221CD4E200184CFC /* NSFont.swift */,
|
||||||
E435E3E3221CD75D00184CFC /* NSImage.swift */,
|
E435E3E3221CD75D00184CFC /* NSImage.swift */,
|
||||||
E408D3B8220DE98F0006D9BE /* NSUserInterfaceItemIdentifier.swift */,
|
E408D3B8220DE98F0006D9BE /* NSUserInterfaceItemIdentifier.swift */,
|
||||||
|
E489E39822B85D0400CA8CBD /* NSPasteboard.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -957,6 +960,7 @@
|
|||||||
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */,
|
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */,
|
||||||
E4B11B61226A4C000075461B /* PlayerReducer.swift in Sources */,
|
E4B11B61226A4C000075461B /* PlayerReducer.swift in Sources */,
|
||||||
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */,
|
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */,
|
||||||
|
E489E39922B85D0400CA8CBD /* NSPasteboard.swift in Sources */,
|
||||||
E465049A21E94DF500A70F4C /* WindowController.swift in Sources */,
|
E465049A21E94DF500A70F4C /* WindowController.swift in Sources */,
|
||||||
E41B22C621FB932700D544F6 /* MPDClient.swift in Sources */,
|
E41B22C621FB932700D544F6 /* MPDClient.swift in Sources */,
|
||||||
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */,
|
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */,
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class QueueViewController: NSViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
||||||
queueView.registerForDraggedTypes([REORDER_PASTEBOARD_TYPE])
|
queueView.registerForDraggedTypes([.songPasteboardType])
|
||||||
queueView.draggingDestinationFeedbackStyle = .regular
|
queueView.draggingDestinationFeedbackStyle = .regular
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,16 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {
|
||||||
|
let item = albumSongs[row]
|
||||||
|
|
||||||
|
let pasteboardItem = NSPasteboardItem()
|
||||||
|
|
||||||
|
pasteboardItem.setPropertyList(["songUri": item.song?.mpdSong.uriString], forType: .songPasteboardType)
|
||||||
|
|
||||||
|
return pasteboardItem
|
||||||
|
}
|
||||||
|
|
||||||
func numberOfRows(in tableView: NSTableView) -> Int {
|
func numberOfRows(in tableView: NSTableView) -> Int {
|
||||||
return albumSongs.count
|
return albumSongs.count
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
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
|
||||||
@ -47,7 +45,7 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
|
|
||||||
let pasteboardItem = NSPasteboardItem()
|
let pasteboardItem = NSPasteboardItem()
|
||||||
|
|
||||||
pasteboardItem.setPropertyList(["queuePos": queueItem.queuePos], forType: REORDER_PASTEBOARD_TYPE)
|
pasteboardItem.setPropertyList(["queuePos": queueItem.queuePos], forType: .songPasteboardType)
|
||||||
|
|
||||||
return pasteboardItem
|
return pasteboardItem
|
||||||
}
|
}
|
||||||
@ -56,34 +54,50 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
var newQueuePos = index - 1
|
var newQueuePos = index - 1
|
||||||
|
|
||||||
guard let draggingTypes = info.draggingPasteboard.types,
|
guard let draggingTypes = info.draggingPasteboard.types,
|
||||||
draggingTypes.contains(REORDER_PASTEBOARD_TYPE),
|
draggingTypes.contains(.songPasteboardType)
|
||||||
let payload = info.draggingPasteboard.propertyList(forType: REORDER_PASTEBOARD_TYPE) as? [String: Int],
|
else { return [] }
|
||||||
|
|
||||||
|
if let payload = info.draggingPasteboard.propertyList(forType: .songPasteboardType) as? [String: Int],
|
||||||
let queuePos = payload["queuePos"],
|
let queuePos = payload["queuePos"],
|
||||||
newQueuePos >= 0
|
newQueuePos >= 0 {
|
||||||
else { return [] }
|
|
||||||
|
|
||||||
if newQueuePos > queuePos { newQueuePos -= 1 }
|
if newQueuePos > queuePos { newQueuePos -= 1 }
|
||||||
|
|
||||||
guard queuePos != newQueuePos
|
guard queuePos != newQueuePos
|
||||||
else { return [] }
|
else { return [] }
|
||||||
|
|
||||||
return .move
|
return .move
|
||||||
|
} else if let payload = info.draggingPasteboard.propertyList(forType: .songPasteboardType) as? [String: String],
|
||||||
|
let _ = payload["songUri"],
|
||||||
|
newQueuePos >= 0 {
|
||||||
|
return .copy
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
|
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
|
||||||
var newQueuePos = index - 1
|
var newQueuePos = index - 1
|
||||||
|
|
||||||
guard let payload = info.draggingPasteboard.propertyList(forType: REORDER_PASTEBOARD_TYPE) as? [String: Int],
|
if let payload = info.draggingPasteboard.propertyList(forType: .songPasteboardType) as? [String: Int],
|
||||||
let queuePos = payload["queuePos"]
|
let queuePos = payload["queuePos"] {
|
||||||
else { return false }
|
|
||||||
|
|
||||||
if newQueuePos > queuePos { newQueuePos -= 1 }
|
if newQueuePos > queuePos { newQueuePos -= 1 }
|
||||||
|
|
||||||
guard queuePos != newQueuePos
|
guard queuePos != newQueuePos
|
||||||
else { return false }
|
else { return false }
|
||||||
|
|
||||||
App.store.dispatch(MPDMoveSongInQueue(oldQueuePos: queuePos, newQueuePos: newQueuePos))
|
App.store.dispatch(MPDMoveSongInQueue(oldQueuePos: queuePos, newQueuePos: newQueuePos))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
} else if let payload = info.draggingPasteboard.propertyList(forType: .songPasteboardType) as? [String: String],
|
||||||
|
let songUri = payload["songUri"] {
|
||||||
|
|
||||||
|
App.store.dispatch(MPDAddSongToQueue(songUri: songUri, queuePos: newQueuePos))
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
Persephone/Extensions/NSPasteboard.swift
Normal file
13
Persephone/Extensions/NSPasteboard.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// NSPasteboard.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/6/17.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
extension NSPasteboard.PasteboardType {
|
||||||
|
static let songPasteboardType = NSPasteboard.PasteboardType("me.danbarber.persephone")
|
||||||
|
}
|
||||||
@ -75,6 +75,12 @@ extension MPDClient {
|
|||||||
else { return }
|
else { return }
|
||||||
sendMoveSongInQueue(at: oldQueuePos, to: newQueuePos)
|
sendMoveSongInQueue(at: oldQueuePos, to: newQueuePos)
|
||||||
|
|
||||||
|
case .addSongToQueue:
|
||||||
|
guard let songUri = userData["uri"] as? String,
|
||||||
|
let queuePos = userData["queuePos"] as? Int
|
||||||
|
else { return }
|
||||||
|
sendAddSongToQueue(uri: songUri, at: queuePos)
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case .fetchAllAlbums:
|
case .fetchAllAlbums:
|
||||||
allAlbums()
|
allAlbums()
|
||||||
|
|||||||
@ -34,6 +34,10 @@ extension MPDClient {
|
|||||||
enqueueCommand(command: .moveSongInQueue, userData: ["oldQueuePos": queuePos, "newQueuePos": newQueuePos])
|
enqueueCommand(command: .moveSongInQueue, userData: ["oldQueuePos": queuePos, "newQueuePos": newQueuePos])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addSongToQueue(songUri: String, at queuePos: Int) {
|
||||||
|
enqueueCommand(command: .addSongToQueue, userData: ["uri": songUri, "queuePos": queuePos])
|
||||||
|
}
|
||||||
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
@ -72,4 +76,8 @@ extension MPDClient {
|
|||||||
func sendMoveSongInQueue(at oldQueuePos: Int, to newQueuePos: Int) {
|
func sendMoveSongInQueue(at oldQueuePos: Int, to newQueuePos: Int) {
|
||||||
mpd_run_move(self.connection, UInt32(oldQueuePos), UInt32(newQueuePos))
|
mpd_run_move(self.connection, UInt32(oldQueuePos), UInt32(newQueuePos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendAddSongToQueue(uri: String, at queuePos: Int) {
|
||||||
|
mpd_run_add_id_to(self.connection, uri, UInt32(queuePos))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ extension MPDClient {
|
|||||||
case appendSong
|
case appendSong
|
||||||
case removeSong
|
case removeSong
|
||||||
case moveSongInQueue
|
case moveSongInQueue
|
||||||
|
case addSongToQueue
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case fetchAllAlbums
|
case fetchAllAlbums
|
||||||
|
|||||||
@ -23,6 +23,11 @@ struct MPDMoveSongInQueue: Action {
|
|||||||
let newQueuePos: Int
|
let newQueuePos: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MPDAddSongToQueue: Action {
|
||||||
|
let songUri: String
|
||||||
|
let queuePos: Int
|
||||||
|
}
|
||||||
|
|
||||||
struct MPDAppendTrack: Action {
|
struct MPDAppendTrack: Action {
|
||||||
let song: MPDClient.MPDSong
|
let song: MPDClient.MPDSong
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,9 @@ func mpdReducer(action: Action, state: MPDState?) -> MPDState {
|
|||||||
case let action as MPDMoveSongInQueue:
|
case let action as MPDMoveSongInQueue:
|
||||||
App.mpdClient.moveSongInQueue(at: action.oldQueuePos, to: action.newQueuePos)
|
App.mpdClient.moveSongInQueue(at: action.oldQueuePos, to: action.newQueuePos)
|
||||||
|
|
||||||
|
case let action as MPDAddSongToQueue:
|
||||||
|
App.mpdClient.addSongToQueue(songUri: action.songUri, at: action.queuePos)
|
||||||
|
|
||||||
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