1
1
mirror of https://github.com/danbee/persephone synced 2025-03-04 08:39:11 +00:00

Redesign queue view

* Add cover art for each track
* Stack song title and artist
* Add song duration
* Redesign the dragged image view to match
This commit is contained in:
Daniel Barber 2020-01-22 22:23:59 -05:00
parent 6458b7402b
commit a8987029f5
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
33 changed files with 512 additions and 266 deletions

View File

@ -18,7 +18,6 @@
E408D3C2220E134F0006D9BE /* AlbumViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E408D3C1220E134F0006D9BE /* AlbumViewController.swift */; }; E408D3C2220E134F0006D9BE /* AlbumViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E408D3C1220E134F0006D9BE /* AlbumViewController.swift */; };
E408D3CB220E341D0006D9BE /* AlbumViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = E408D3C9220E341D0006D9BE /* AlbumViewItem.xib */; }; E408D3CB220E341D0006D9BE /* AlbumViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = E408D3C9220E341D0006D9BE /* AlbumViewItem.xib */; };
E40FE71B221B904300A4223F /* NSEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E40FE71A221B904300A4223F /* NSEvent.swift */; }; E40FE71B221B904300A4223F /* NSEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E40FE71A221B904300A4223F /* NSEvent.swift */; };
E4120D6C22AD8139004CB1F8 /* QueueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4120D6B22AD8139004CB1F8 /* QueueView.swift */; };
E419E2872249B96600216A8C /* Song.swift in Sources */ = {isa = PBXBuildFile; fileRef = E419E2862249B96600216A8C /* Song.swift */; }; E419E2872249B96600216A8C /* Song.swift in Sources */ = {isa = PBXBuildFile; fileRef = E419E2862249B96600216A8C /* Song.swift */; };
E41B22C621FB932700D544F6 /* MPDClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41B22C521FB932700D544F6 /* MPDClient.swift */; }; E41B22C621FB932700D544F6 /* MPDClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41B22C521FB932700D544F6 /* MPDClient.swift */; };
E41E52FD223BF87300173814 /* MPDClient+Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E52FC223BF87300173814 /* MPDClient+Connection.swift */; }; E41E52FD223BF87300173814 /* MPDClient+Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E52FC223BF87300173814 /* MPDClient+Connection.swift */; };
@ -30,7 +29,7 @@
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5308223C020400173814 /* MPDClient+Command.swift */; }; E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5308223C020400173814 /* MPDClient+Command.swift */; };
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530A223C033700173814 /* MPDClient+Album.swift */; }; E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530A223C033700173814 /* MPDClient+Album.swift */; };
E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */; }; E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */; };
E4235640228623D2001216D6 /* QueueSongTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E423563F228623D2001216D6 /* QueueSongTitleView.swift */; }; E4235640228623D2001216D6 /* QueueSongInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E423563F228623D2001216D6 /* QueueSongInfoView.swift */; };
E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42410B52241B956005ED6DF /* MPDClient+Database.swift */; }; E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42410B52241B956005ED6DF /* MPDClient+Database.swift */; };
E42A4D4F22E20D7D001C6CAD /* MPDTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42A4D4E22E20D7D001C6CAD /* MPDTag.swift */; }; E42A4D4F22E20D7D001C6CAD /* MPDTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42A4D4E22E20D7D001C6CAD /* MPDTag.swift */; };
E42A4D5122E2167E001C6CAD /* MPDClient+Songs.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42A4D5022E2167E001C6CAD /* MPDClient+Songs.swift */; }; E42A4D5122E2167E001C6CAD /* MPDClient+Songs.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42A4D5022E2167E001C6CAD /* MPDClient+Songs.swift */; };
@ -99,6 +98,7 @@
E4B11BBE2275EDAA0075461B /* PlayerActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BBD2275EDAA0075461B /* PlayerActions.swift */; }; E4B11BBE2275EDAA0075461B /* PlayerActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BBD2275EDAA0075461B /* PlayerActions.swift */; };
E4B11BC02275EE150075461B /* QueueActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BBF2275EE150075461B /* QueueActions.swift */; }; E4B11BC02275EE150075461B /* QueueActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BBF2275EE150075461B /* QueueActions.swift */; };
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BC12275EE410075461B /* AlbumListActions.swift */; }; E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11BC12275EE410075461B /* AlbumListActions.swift */; };
E4B3DF6523D66A4400728F6B /* QueueSongCoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B3DF6423D66A4400728F6B /* QueueSongCoverView.swift */; };
E4B5AE7E22F4C49600CCEC65 /* MPDServerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B5AE7D22F4C49600CCEC65 /* MPDServerDelegate.swift */; }; E4B5AE7E22F4C49600CCEC65 /* MPDServerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B5AE7D22F4C49600CCEC65 /* MPDServerDelegate.swift */; };
E4BBD2F323357C0700702C16 /* ArtistListState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4BBD2F223357C0700702C16 /* ArtistListState.swift */; }; E4BBD2F323357C0700702C16 /* ArtistListState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4BBD2F223357C0700702C16 /* ArtistListState.swift */; };
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */; }; E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */; };
@ -183,7 +183,6 @@
E408D3C1220E134F0006D9BE /* AlbumViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumViewController.swift; sourceTree = "<group>"; }; E408D3C1220E134F0006D9BE /* AlbumViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumViewController.swift; sourceTree = "<group>"; };
E408D3C9220E341D0006D9BE /* AlbumViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AlbumViewItem.xib; sourceTree = "<group>"; }; E408D3C9220E341D0006D9BE /* AlbumViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AlbumViewItem.xib; sourceTree = "<group>"; };
E40FE71A221B904300A4223F /* NSEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEvent.swift; sourceTree = "<group>"; }; E40FE71A221B904300A4223F /* NSEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEvent.swift; sourceTree = "<group>"; };
E4120D6B22AD8139004CB1F8 /* QueueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueView.swift; sourceTree = "<group>"; };
E419E2862249B96600216A8C /* Song.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Song.swift; sourceTree = "<group>"; }; E419E2862249B96600216A8C /* Song.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Song.swift; sourceTree = "<group>"; };
E41B22BF21FB6BBA00D544F6 /* libmpdclient.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmpdclient.2.dylib; path = libmpdclient/output/libmpdclient.2.dylib; sourceTree = "<group>"; }; E41B22BF21FB6BBA00D544F6 /* libmpdclient.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmpdclient.2.dylib; path = libmpdclient/output/libmpdclient.2.dylib; sourceTree = "<group>"; };
E41B22C421FB715A00D544F6 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; }; E41B22C421FB715A00D544F6 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@ -232,7 +231,7 @@
E41E5308223C020400173814 /* MPDClient+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Command.swift"; sourceTree = "<group>"; }; E41E5308223C020400173814 /* MPDClient+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Command.swift"; sourceTree = "<group>"; };
E41E530A223C033700173814 /* MPDClient+Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Album.swift"; sourceTree = "<group>"; }; E41E530A223C033700173814 /* MPDClient+Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Album.swift"; sourceTree = "<group>"; };
E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPrefsViewController.swift; sourceTree = "<group>"; }; E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPrefsViewController.swift; sourceTree = "<group>"; };
E423563F228623D2001216D6 /* QueueSongTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueSongTitleView.swift; sourceTree = "<group>"; }; E423563F228623D2001216D6 /* QueueSongInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueSongInfoView.swift; sourceTree = "<group>"; };
E42410B52241B956005ED6DF /* MPDClient+Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Database.swift"; sourceTree = "<group>"; }; E42410B52241B956005ED6DF /* MPDClient+Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Database.swift"; sourceTree = "<group>"; };
E42A4D4E22E20D7D001C6CAD /* MPDTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDTag.swift; sourceTree = "<group>"; }; E42A4D4E22E20D7D001C6CAD /* MPDTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDTag.swift; sourceTree = "<group>"; };
E42A4D5022E2167E001C6CAD /* MPDClient+Songs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Songs.swift"; sourceTree = "<group>"; }; E42A4D5022E2167E001C6CAD /* MPDClient+Songs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Songs.swift"; sourceTree = "<group>"; };
@ -293,6 +292,7 @@
E4B11BBD2275EDAA0075461B /* PlayerActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerActions.swift; sourceTree = "<group>"; }; E4B11BBD2275EDAA0075461B /* PlayerActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerActions.swift; sourceTree = "<group>"; };
E4B11BBF2275EE150075461B /* QueueActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueActions.swift; sourceTree = "<group>"; }; E4B11BBF2275EE150075461B /* QueueActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueActions.swift; sourceTree = "<group>"; };
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>"; };
E4B3DF6423D66A4400728F6B /* QueueSongCoverView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueSongCoverView.swift; sourceTree = "<group>"; };
E4B5AE7D22F4C49600CCEC65 /* MPDServerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDServerDelegate.swift; sourceTree = "<group>"; }; E4B5AE7D22F4C49600CCEC65 /* MPDServerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDServerDelegate.swift; sourceTree = "<group>"; };
E4BBD2F223357C0700702C16 /* ArtistListState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistListState.swift; sourceTree = "<group>"; }; E4BBD2F223357C0700702C16 /* ArtistListState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistListState.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>"; };
@ -537,8 +537,8 @@
children = ( children = (
E4B11BB7227538FA0075461B /* CurrentCoverArtView.swift */, E4B11BB7227538FA0075461B /* CurrentCoverArtView.swift */,
E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */, E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */,
E423563F228623D2001216D6 /* QueueSongTitleView.swift */, E4B3DF6423D66A4400728F6B /* QueueSongCoverView.swift */,
E4120D6B22AD8139004CB1F8 /* QueueView.swift */, E423563F228623D2001216D6 /* QueueSongInfoView.swift */,
E4E8CC912204F4B80024217A /* QueueViewController.swift */, E4E8CC912204F4B80024217A /* QueueViewController.swift */,
E4D3BFA522B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift */, E4D3BFA522B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift */,
); );
@ -935,7 +935,7 @@
E442CCCD2347E73C00004E0C /* Artist.swift in Sources */, E442CCCD2347E73C00004E0C /* Artist.swift in Sources */,
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */, E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */,
E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */, E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */,
E4235640228623D2001216D6 /* QueueSongTitleView.swift in Sources */, E4235640228623D2001216D6 /* QueueSongInfoView.swift in Sources */,
E451E36E22BD2501008BE9B2 /* DraggedSong.swift in Sources */, E451E36E22BD2501008BE9B2 /* DraggedSong.swift in Sources */,
E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */, E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */,
E4B11BC02275EE150075461B /* QueueActions.swift in Sources */, E4B11BC02275EE150075461B /* QueueActions.swift in Sources */,
@ -971,6 +971,7 @@
E44051A0227BB0AB0090CD6F /* UIState.swift in Sources */, E44051A0227BB0AB0090CD6F /* UIState.swift in Sources */,
E4FF718E2276010E00D4C412 /* PreferencesState.swift in Sources */, E4FF718E2276010E00D4C412 /* PreferencesState.swift in Sources */,
E439109822640213002982E9 /* SongNotifierService.swift in Sources */, E439109822640213002982E9 /* SongNotifierService.swift in Sources */,
E4B3DF6523D66A4400728F6B /* QueueSongCoverView.swift in Sources */,
E407861C2110CE6E006887B1 /* AppDelegate.swift in Sources */, E407861C2110CE6E006887B1 /* AppDelegate.swift in Sources */,
E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */, E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */,
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */, E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */,
@ -985,7 +986,6 @@
E4B5AE7E22F4C49600CCEC65 /* MPDServerDelegate.swift in Sources */, E4B5AE7E22F4C49600CCEC65 /* MPDServerDelegate.swift in Sources */,
E4B11BB8227538FA0075461B /* CurrentCoverArtView.swift in Sources */, E4B11BB8227538FA0075461B /* CurrentCoverArtView.swift in Sources */,
E4E8CC9A22075D370024217A /* MPDSong.swift in Sources */, E4E8CC9A22075D370024217A /* MPDSong.swift in Sources */,
E4120D6C22AD8139004CB1F8 /* QueueView.swift in Sources */,
E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */, E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */,
E4E8CC902204EC7F0024217A /* Delegate.swift in Sources */, E4E8CC902204EC7F0024217A /* Delegate.swift in Sources */,
E47E2FD5222071FD00F747E6 /* AlbumViewItem.swift in Sources */, E47E2FD5222071FD00F747E6 /* AlbumViewItem.swift in Sources */,

View File

@ -0,0 +1,54 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "pauseButton.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "pauseButtonWhite.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "pauseButton@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "pauseButtonWhite@2x.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"idiom" : "universal",
"scale" : "3x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

View File

@ -0,0 +1,54 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "playButton.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "playButtonWhite.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "playButton@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "playButtonWhite@2x.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"idiom" : "universal",
"scale" : "3x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

View File

@ -145,6 +145,18 @@ class AlbumDetailView: NSViewController {
.scaleFactor(2), .scaleFactor(2),
] ]
) )
cacheSmallCover(provider: provider)
}
func cacheSmallCover(provider: ImageDataProvider) {
_ = KingfisherManager.shared.retrieveImage(
with: .provider(provider),
options: [
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
.scaleFactor(2),
]
) { result in }
} }
func setAppearance() { func setAppearance() {

View File

@ -49,7 +49,8 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
draggedSong: DraggedSong( draggedSong: DraggedSong(
type: .albumSongItem(song.mpdSong.uriString), type: .albumSongItem(song.mpdSong.uriString),
title: song.title, title: song.title,
artist: song.artist artist: song.artist,
cover: song.album.coverArtFilePath
), ),
ofType: .songPasteboardType ofType: .songPasteboardType
) )
@ -68,12 +69,20 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
) { draggingItem, index, stop in ) { draggingItem, index, stop in
guard let item = draggingItem.item as? NSPasteboardItem, guard let item = draggingItem.item as? NSPasteboardItem,
let draggedSong = item.draggedSong(forType: .songPasteboardType), let draggedSong = item.draggedSong(forType: .songPasteboardType),
case let (title?, artist?) = (draggedSong.title, draggedSong.artist) case let (title?, artist?, cover?) = (
draggedSong.title,
draggedSong.artist,
draggedSong.cover
)
else { return } else { return }
draggingItem.imageComponentsProvider = { draggingItem.imageComponentsProvider = {
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon) let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
let draggedSongView = DraggedSongView(title: title, artist: artist) let draggedSongView = DraggedSongView(
title: title,
artist: artist,
cover: cover
)
component.contents = draggedSongView.view.image() component.contents = draggedSongView.view.image()
component.frame = NSRect(origin: CGPoint(), size: draggedSongView.view.image().size) component.frame = NSRect(origin: CGPoint(), size: draggedSongView.view.image().size)

View File

@ -15,16 +15,16 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
func setQueueIcon(_ state: QueueState) { func setQueueIcon(_ state: QueueState) {
switch state.state { switch state.state {
case .playing?: case .playing?:
queueIcon = .playIcon queueIcon = .queuePlayIcon
case .paused?: case .paused?:
queueIcon = .pauseIcon queueIcon = .queuePauseIcon
default: default:
queueIcon = nil queueIcon = nil
} }
} }
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
return queue.count + 1 return queue.count
} }
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
@ -32,11 +32,7 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
} }
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
if index > 0 { return queue[index]
return queue[index - 1]
} else {
return ""
}
} }
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? { func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
@ -47,14 +43,15 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
draggedSong: DraggedSong( draggedSong: DraggedSong(
type: .queueItem(queueItem.queuePos), type: .queueItem(queueItem.queuePos),
title: queueItem.song.title, title: queueItem.song.title,
artist: queueItem.song.artist artist: queueItem.song.artist,
cover: queueItem.song.album.coverArtFilePath
), ),
ofType: .songPasteboardType ofType: .songPasteboardType
) )
} }
func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation { func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
var newQueuePos = index - 1 var newQueuePos = index
guard newQueuePos >= 0, guard newQueuePos >= 0,
let draggingTypes = info.draggingPasteboard.types let draggingTypes = info.draggingPasteboard.types
@ -84,7 +81,7 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
} }
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
guard let draggingTypes = info.draggingPasteboard.types guard let draggingTypes = info.draggingPasteboard.types
else { return false } else { return false }
@ -131,12 +128,20 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
guard let item = draggingItem.item as? NSPasteboardItem, guard let item = draggingItem.item as? NSPasteboardItem,
let data = item.data(forType: .songPasteboardType), let data = item.data(forType: .songPasteboardType),
let draggedSong = try? PropertyListDecoder().decode(DraggedSong.self, from: data), let draggedSong = try? PropertyListDecoder().decode(DraggedSong.self, from: data),
case let (title?, artist?) = (draggedSong.title, draggedSong.artist) case let (title?, artist?, cover?) = (
draggedSong.title,
draggedSong.artist,
draggedSong.cover
)
else { return } else { return }
draggingItem.imageComponentsProvider = { draggingItem.imageComponentsProvider = {
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon) let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
let draggedSongView = DraggedSongView(title: title, artist: artist) let draggedSongView = DraggedSongView(
title: title,
artist: artist,
cover: cover
)
let view = draggedSongView.view let view = draggedSongView.view
let image = view.image() let image = view.image()

View File

@ -0,0 +1,86 @@
//
// QueueSongCoverView.swift
// Persephone
//
// Created by Daniel Barber on 1/20/20.
// Copyright © 2020 Dan Barber. All rights reserved.
//
import AppKit
import Kingfisher
class QueueSongCoverView: NSTableCellView {
@IBOutlet var queueSongCover: NSImageView!
@IBOutlet var queueSongButton: NSButton!
let playingFilters = [
CIFilter(name: "CIExposureAdjust", parameters: ["inputEV": -2])!
]
var isPlaying: Bool = false
override func viewDidMoveToSuperview() {
super.viewDidMoveToSuperview()
queueSongCover.wantsLayer = true
queueSongCover.layer?.backgroundColor = CGColor.black
queueSongCover.layer?.cornerRadius = 2
queueSongCover.layer?.borderWidth = 1
queueSongCover.layer?.masksToBounds = true
queueSongButton.wantsLayer = true
setAppearance()
if isPlaying {
queueSongCover.layer?.filters = playingFilters
} else {
queueSongCover.layer?.filters = nil
}
}
override func prepareForReuse() {
super.prepareForReuse()
queueSongCover.image = .defaultCoverArt
}
func setAppearance() {
guard let viewLayer = queueSongCover.layer
else { return }
if #available(OSX 10.14, *) {
let darkMode = NSApp.effectiveAppearance.bestMatch(from:
[.darkAqua, .aqua]) == .darkAqua
viewLayer.borderColor = darkMode ? .albumBorderColorDark : .albumBorderColorLight
} else {
viewLayer.borderColor = .albumBorderColorLight
}
}
func setSong(_ queueItem: QueueItem, queueIcon: NSImage?) {
guard let imagePath = queueItem.song.album.coverArtFilePath
else { return }
isPlaying = queueItem.isPlaying
let imageURL = URL(fileURLWithPath: imagePath)
let provider = LocalFileImageDataProvider(fileURL: imageURL)
queueSongCover.kf.setImage(
with: .provider(provider),
placeholder: NSImage.defaultCoverArt,
options: [
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
.scaleFactor(2),
]
)
if isPlaying && queueIcon != nil {
queueSongCover.layer?.filters = playingFilters
queueSongButton.image = queueIcon
} else {
queueSongCover.layer?.filters = nil
queueSongButton.image = nil
}
}
}

View File

@ -8,23 +8,18 @@
import AppKit import AppKit
class QueueSongTitleView: NSTableCellView { class QueueSongInfoView: NSTableCellView {
@IBOutlet var queuePlayerStateImage: NSImageView!
@IBOutlet var queuePosition: NSTextField!
@IBOutlet var queueSongTitle: NSTextField! @IBOutlet var queueSongTitle: NSTextField!
@IBOutlet var queueSongArtist: NSTextField!
func setQueueSong(_ queueItem: QueueItem, queueIcon: NSImage?) { func setSong(_ queueItem: QueueItem, queueIcon: NSImage?) {
queuePosition?.font = .timerFont
queueSongTitle?.stringValue = queueItem.song.title queueSongTitle?.stringValue = queueItem.song.title
queueSongArtist?.stringValue = queueItem.song.artist
if queueItem.isPlaying && queueIcon != nil { if queueItem.isPlaying && queueIcon != nil {
queueSongTitle?.font = .systemFontBold queueSongTitle?.font = .systemFontBold
queuePlayerStateImage?.image = queueIcon
queuePosition?.stringValue = ""
} else { } else {
queueSongTitle?.font = .systemFontRegular queueSongTitle?.font = .systemFontRegular
queuePlayerStateImage?.image = nil
queuePosition?.stringValue = "\(queueItem.queuePos + 1)."
} }
} }
} }

View File

@ -1,23 +0,0 @@
//
// QueueView.swift
// Persephone
//
// Created by Daniel Barber on 2019/6/09.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import AppKit
class QueueView: NSOutlineView {
override func menu(for event: NSEvent) -> NSMenu? {
let point = convert(event.locationInWindow, from: nil)
let currentRow = row(at: point)
if currentRow > 0 {
return super.menu(for: event)
} else {
return nil
}
}
}

View File

@ -9,78 +9,59 @@
import AppKit import AppKit
extension QueueViewController: NSOutlineViewDelegate { 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? { func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
if let queueItem = item as? QueueItem { if let queueItem = item as? QueueItem {
switch tableColumn?.identifier.rawValue { switch tableColumn?.identifier.rawValue {
case "songTitleColumn": case "songCoverColumn":
return cellForSongTitle(outlineView, with: queueItem) return cellForSongCover(outlineView, with: queueItem)
case "songArtistColumn": case "songInfoColumn":
return cellForSongArtist(outlineView, with: queueItem) return cellForSongInfo(outlineView, with: queueItem)
case "songDurationColumn":
return cellForSongDuration(outlineView, with: queueItem)
default: default:
return nil return nil
} }
} else if tableColumn?.identifier.rawValue == "songTitleColumn" {
return cellForQueueHeading(outlineView)
} else { } else {
return nil return nil
} }
} }
func outlineViewSelectionDidChange(_ notification: Notification) { func outlineViewSelectionDidChange(_ notification: Notification) {
if queueView.selectedRow >= 1 { let queueItem = dataSource.queue[queueView.selectedRow]
let queueItem = dataSource.queue[queueView.selectedRow - 1]
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: queueItem)) App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: queueItem))
} else {
App.store.dispatch(SetSelectedQueueItem(selectedQueueItem: nil))
}
} }
func cellForSongTitle(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView { func cellForSongCover(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
let cellView = outlineView.makeView( let cellView = outlineView.makeView(
withIdentifier: .queueSongTitle, withIdentifier: .queueSongCover,
owner: self owner: self
) as! QueueSongTitleView ) as! QueueSongCoverView
cellView.setQueueSong(queueItem, queueIcon: dataSource.queueIcon) cellView.setSong(queueItem, queueIcon: dataSource.queueIcon)
return cellView return cellView
} }
func cellForSongArtist(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView { func cellForSongInfo(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
let cellView = outlineView.makeView( let cellView = outlineView.makeView(
withIdentifier: .queueSongArtist, withIdentifier: .queueSongInfo,
owner: self owner: self
) as! NSTableCellView ) as! QueueSongInfoView
cellView.textField?.stringValue = queueItem.song.artist cellView.setSong(queueItem, queueIcon: dataSource.queueIcon)
if queueItem.isPlaying {
cellView.textField?.font = .systemFontBold
} else {
cellView.textField?.font = .systemFontRegular
}
return cellView return cellView
} }
func cellForQueueHeading(_ outlineView: NSOutlineView) -> NSView { func cellForSongDuration(_ outlineView: NSOutlineView, with queueItem: QueueItem) -> NSView {
let cellView = outlineView.makeView( let cellView = outlineView.makeView(
withIdentifier: .queueHeading, withIdentifier: .queueSongDuration,
owner: self owner: self
) as! NSTableCellView ) as! NSTableCellView
cellView.textField?.stringValue = "QUEUE" cellView.textField?.font = .timerFont
cellView.textField?.stringValue = queueItem.song.duration.formattedTime
return cellView return cellView
} }

View File

@ -40,11 +40,9 @@ class QueueViewController: NSViewController {
case NSEvent.keyCodeSpace: case NSEvent.keyCodeSpace:
nextResponder?.keyDown(with: event) nextResponder?.keyDown(with: event)
case NSEvent.keyCodeBS: case NSEvent.keyCodeBS:
let queuePos = queueView.selectedRow - 1 let queuePos = queueView.selectedRow
if queuePos >= 0 {
App.mpdClient.removeSong(at: queuePos) App.mpdClient.removeSong(at: queuePos)
}
default: default:
super.keyDown(with: event) super.keyDown(with: event)
} }
@ -62,27 +60,21 @@ class QueueViewController: NSViewController {
} }
@IBAction func playTrack(_ sender: Any) { @IBAction func playTrack(_ sender: Any) {
let queuePos = queueView.selectedRow - 1 let queuePos = queueView.selectedRow
if queuePos >= 0 {
App.mpdClient.playTrack(at: queuePos) App.mpdClient.playTrack(at: queuePos)
} }
}
@IBAction func playSongMenuAction(_ sender: NSMenuItem) { @IBAction func playSongMenuAction(_ sender: NSMenuItem) {
let queuePos = queueView.clickedRow - 1 let queuePos = queueView.clickedRow
if queuePos >= 0 {
App.mpdClient.playTrack(at: queuePos) App.mpdClient.playTrack(at: queuePos)
} }
}
@IBAction func removeSongMenuAction(_ sender: NSMenuItem) { @IBAction func removeSongMenuAction(_ sender: NSMenuItem) {
let queuePos = queueView.clickedRow - 1 let queuePos = queueView.clickedRow
if queuePos >= 0 {
App.mpdClient.removeSong(at: queuePos) App.mpdClient.removeSong(at: queuePos)
} }
}
} }
extension QueueViewController: StoreSubscriber { extension QueueViewController: StoreSubscriber {

View File

@ -7,17 +7,22 @@
// //
import Cocoa import Cocoa
import Kingfisher
class DraggedSongView: NSViewController { class DraggedSongView: NSViewController {
@IBOutlet var titleLabel: NSTextField! @IBOutlet var titleLabel: NSTextField!
@IBOutlet var artistLabel: NSTextField! @IBOutlet var artistLabel: NSTextField!
@IBOutlet var coverImage: NSImageView!
private let songTitle: String private let songTitle: String
private let songArtist: String private let songArtist: String
private let songCover: String?
init(title: String, artist: String) { init(title: String, artist: String, cover: String? = nil) {
songTitle = title songTitle = title
songArtist = artist songArtist = artist
songCover = cover
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
@ -27,7 +32,44 @@ class DraggedSongView: NSViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
coverImage.wantsLayer = true
coverImage.layer?.backgroundColor = CGColor.black
coverImage.layer?.cornerRadius = 2
coverImage.layer?.borderWidth = 1
coverImage.layer?.masksToBounds = true
setAppearance()
titleLabel.stringValue = songTitle titleLabel.stringValue = songTitle
artistLabel.stringValue = songArtist artistLabel.stringValue = songArtist
setCoverArt()
}
func setAppearance() {
if #available(OSX 10.14, *) {
let darkMode = NSApp.effectiveAppearance.bestMatch(from:
[.darkAqua, .aqua]) == .darkAqua
coverImage.layer?.borderColor = darkMode ? .albumBorderColorDark : .albumBorderColorLight
} else {
coverImage.layer?.borderColor = .albumBorderColorLight
}
}
func setCoverArt() {
guard let imagePath = songCover else { return }
let imageURL = URL(fileURLWithPath: imagePath)
let provider = LocalFileImageDataProvider(fileURL: imageURL)
coverImage.kf.setImage(
with: .provider(provider),
placeholder: NSImage.defaultCoverArt,
options: [
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
.scaleFactor(2),
]
)
} }
} }

View File

@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="DraggedSongView" customModule="Persephone" customModuleProvider="target"> <customObject id="-2" userLabel="File's Owner" customClass="DraggedSongView" customModule="Persephone" customModuleProvider="target">
<connections> <connections>
<outlet property="artistLabel" destination="egC-YO-gnV" id="g0f-FI-cGF"/> <outlet property="artistLabel" destination="egC-YO-gnV" id="g0f-FI-cGF"/>
<outlet property="coverImage" destination="Go5-Lk-qgA" id="M4D-rz-VvO"/>
<outlet property="titleLabel" destination="tsD-ub-h7I" id="EVO-Z7-tZY"/> <outlet property="titleLabel" destination="tsD-ub-h7I" id="EVO-Z7-tZY"/>
<outlet property="view" destination="Hz6-mo-xeY" id="Wf9-hm-E7M"/> <outlet property="view" destination="Hz6-mo-xeY" id="Wf9-hm-E7M"/>
</connections> </connections>
@ -16,52 +17,63 @@
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/> <customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY"> <customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="129" height="22"/> <rect key="frame" x="0.0" y="0.0" width="110" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews> <subviews>
<box boxType="custom" borderType="line" cornerRadius="4" translatesAutoresizingMaskIntoConstraints="NO" id="G2x-p5-RM6"> <box boxType="custom" borderType="line" cornerRadius="4" translatesAutoresizingMaskIntoConstraints="NO" id="G2x-p5-RM6">
<rect key="frame" x="0.0" y="0.0" width="129" height="22"/> <rect key="frame" x="0.0" y="0.0" width="110" height="44"/>
<view key="contentView" id="qbG-wn-N4h"> <view key="contentView" id="qbG-wn-N4h">
<rect key="frame" x="1" y="1" width="127" height="20"/> <rect key="frame" x="1" y="1" width="108" height="42"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<stackView distribution="fillProportionally" orientation="horizontal" alignment="centerY" spacing="12" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rlT-HP-okZ"> <stackView distribution="fillProportionally" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rlT-HP-okZ">
<rect key="frame" x="0.0" y="0.0" width="127" height="20"/> <rect key="frame" x="0.0" y="0.0" width="108" height="42"/>
<subviews> <subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Go5-Lk-qgA"> <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Go5-Lk-qgA">
<rect key="frame" x="8" y="2" width="17" height="17"/> <rect key="frame" x="8" y="5" width="32" height="32"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="17" id="DKw-m3-Lne"/> <constraint firstAttribute="height" constant="32" id="DKw-m3-Lne"/>
<constraint firstAttribute="width" constant="17" id="k19-kI-PmI"/> <constraint firstAttribute="width" constant="32" id="k19-kI-PmI"/>
</constraints> </constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="songIcon" id="KDX-a9-N4B"/> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="defaultCoverArt" id="KDX-a9-N4B"/>
</imageView> </imageView>
<stackView distribution="fill" orientation="vertical" alignment="leading" spacing="0.0" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="H9H-r5-zq3">
<rect key="frame" x="48" y="6" width="44" height="31"/>
<subviews>
<textField horizontalHuggingPriority="1000" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tsD-ub-h7I"> <textField horizontalHuggingPriority="1000" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tsD-ub-h7I">
<rect key="frame" x="35" y="2" width="32" height="17"/> <rect key="frame" x="-2" y="15" width="31" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" title="Title" usesSingleLineMode="YES" id="rMn-D0-PG7"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" title="Title" usesSingleLineMode="YES" id="rMn-D0-PG7">
<font key="font" metaFont="systemMedium" size="13"/> <font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField horizontalHuggingPriority="1000" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="egC-YO-gnV"> <textField horizontalHuggingPriority="1000" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="egC-YO-gnV">
<rect key="frame" x="75" y="2" width="38" height="17"/> <rect key="frame" x="-2" y="0.0" width="35" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="left" title="Artist" usesSingleLineMode="YES" id="m15-pn-bdW"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="left" title="Artist" usesSingleLineMode="YES" id="m15-pn-bdW">
<font key="font" metaFont="system"/> <font key="font" metaFont="system" size="12"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
</subviews> </subviews>
<edgeInsets key="edgeInsets" left="8" right="16" top="0.0" bottom="0.0"/>
<visibilityPriorities> <visibilityPriorities>
<real value="1000"/>
<integer value="1000"/> <integer value="1000"/>
<integer value="1000"/> <integer value="1000"/>
</visibilityPriorities> </visibilityPriorities>
<customSpacing> <customSpacing>
<real value="3.4028234663852886e+38"/> <real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/> <real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<edgeInsets key="edgeInsets" left="8" right="16" top="0.0" bottom="0.0"/>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/> <real value="3.4028234663852886e+38"/>
</customSpacing> </customSpacing>
</stackView> </stackView>
@ -74,7 +86,7 @@
</constraints> </constraints>
</view> </view>
<color key="borderColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/> <color key="borderColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="fillColor" red="0.27450980392156865" green="0.27450980392156865" blue="0.27450980392156865" alpha="0.65297645246478875" colorSpace="custom" customColorSpace="sRGB"/> <color key="fillColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</box> </box>
</subviews> </subviews>
<constraints> <constraints>
@ -83,10 +95,10 @@
<constraint firstAttribute="trailing" secondItem="G2x-p5-RM6" secondAttribute="trailing" id="MbJ-MP-4HG"/> <constraint firstAttribute="trailing" secondItem="G2x-p5-RM6" secondAttribute="trailing" id="MbJ-MP-4HG"/>
<constraint firstAttribute="bottom" secondItem="G2x-p5-RM6" secondAttribute="bottom" id="Nzd-OC-f1V"/> <constraint firstAttribute="bottom" secondItem="G2x-p5-RM6" secondAttribute="bottom" id="Nzd-OC-f1V"/>
</constraints> </constraints>
<point key="canvasLocation" x="53.5" y="14"/> <point key="canvasLocation" x="-30" y="129"/>
</customView> </customView>
</objects> </objects>
<resources> <resources>
<image name="songIcon" width="17" height="17"/> <image name="defaultCoverArt" width="128" height="128"/>
</resources> </resources>
</document> </document>

View File

@ -11,6 +11,8 @@ import AppKit
extension NSImage { extension NSImage {
static let playIcon = NSImage(named: "playButton") static let playIcon = NSImage(named: "playButton")
static let pauseIcon = NSImage(named: "pauseButton") static let pauseIcon = NSImage(named: "pauseButton")
static let queuePlayIcon = NSImage(named: "queuePlayButton")
static let queuePauseIcon = NSImage(named: "queuePauseButton")
static let defaultCoverArt = NSImage(named: "defaultCoverArt") static let defaultCoverArt = NSImage(named: "defaultCoverArt")

View File

@ -9,6 +9,7 @@
import AppKit import AppKit
extension NSSize { extension NSSize {
static let queueSongCoverSize = NSSize(width: 32, height: 32)
static let albumListCoverSize = NSSize(width: 180, height: 180) static let albumListCoverSize = NSSize(width: 180, height: 180)
static let albumDetailCoverSize = NSSize(width: 500, height: 500) static let albumDetailCoverSize = NSSize(width: 500, height: 500)
static let currentlyPlayingCoverSize = albumDetailCoverSize static let currentlyPlayingCoverSize = albumDetailCoverSize

View File

@ -9,15 +9,13 @@
import AppKit import AppKit
extension NSUserInterfaceItemIdentifier { extension NSUserInterfaceItemIdentifier {
static let queueSongTitleColumn = NSUserInterfaceItemIdentifier("songTitleColumn") static let queueSongInfoColumn = NSUserInterfaceItemIdentifier("songInfoColumn")
static let queueSongArtistColumn = NSUserInterfaceItemIdentifier("songArtistColumn")
static let queueHeading = NSUserInterfaceItemIdentifier("queueHeadingCell") static let queueSongCover = NSUserInterfaceItemIdentifier("songCoverCell")
static let queueSongArtist = NSUserInterfaceItemIdentifier("songArtistCell") static let queueSongInfo = NSUserInterfaceItemIdentifier("songInfoCell")
static let queueSongTitle = NSUserInterfaceItemIdentifier("songTitleCell") static let queueSongDuration = NSUserInterfaceItemIdentifier("songDurationCell")
static let albumViewItem = NSUserInterfaceItemIdentifier("AlbumViewItem") static let albumViewItem = NSUserInterfaceItemIdentifier("AlbumViewItem")
static let artistViewItem = NSUserInterfaceItemIdentifier("ArtistViewItem")
static let discNumber = NSUserInterfaceItemIdentifier("discNumberCell") static let discNumber = NSUserInterfaceItemIdentifier("discNumberCell")
static let trackNumber = NSUserInterfaceItemIdentifier("trackNumberCell") static let trackNumber = NSUserInterfaceItemIdentifier("trackNumberCell")

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS"> <document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
@ -646,27 +646,27 @@
<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" dividerStyle="thin" id="84I-w3-Mxl"> <splitView key="view" misplaced="YES" dividerStyle="thin" id="84I-w3-Mxl">
<rect key="frame" x="0.0" y="0.0" width="328" height="547"/> <rect key="frame" x="0.0" y="0.0" width="329" height="543"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews> <subviews>
<scrollView misplaced="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="17" horizontalPageScroll="10" verticalLineScroll="17" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="S3o-nF-NN7"> <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="42" horizontalPageScroll="10" verticalLineScroll="42" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="S3o-nF-NN7">
<rect key="frame" x="0.0" y="0.0" width="328" height="219"/> <rect key="frame" x="0.0" y="0.0" width="329" height="217"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
<clipView key="contentView" drawsBackground="NO" id="WI8-Pw-03L"> <clipView key="contentView" drawsBackground="NO" id="WI8-Pw-03L">
<rect key="frame" x="0.0" y="0.0" width="328" height="219"/> <rect key="frame" x="0.0" y="0.0" width="329" height="217"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="14" outlineTableColumn="0Co-uF-CCB" id="jEJ-jg-fll" customClass="QueueView" customModule="Persephone" customModuleProvider="target"> <outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" multipleSelection="NO" autosaveColumns="NO" rowHeight="42" rowSizeStyle="automatic" viewBased="YES" indentationMarkerFollowsCell="NO" outlineTableColumn="0Co-uF-CCB" id="jEJ-jg-fll">
<rect key="frame" x="0.0" y="0.0" width="328" height="219"/> <rect key="frame" x="0.0" y="0.0" width="329" height="217"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="0.0"/> <size key="intercellSpacing" width="3" height="0.0"/>
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns> <tableColumns>
<tableColumn identifier="songTitleColumn" width="200" minWidth="128" maxWidth="1000" id="0Co-uF-CCB"> <tableColumn identifier="songCoverColumn" width="43" minWidth="42" maxWidth="1000" id="0Co-uF-CCB" userLabel="Position">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Title"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="message" size="11"/> <font key="font" metaFont="menu" size="11"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell> </tableHeaderCell>
@ -677,107 +677,131 @@
</textFieldCell> </textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView identifier="queueHeadingCell" id="GOd-cg-juD"> <tableCellView identifier="songCoverCell" id="5rR-Gz-AcP" userLabel="Song Cover View" customClass="QueueSongCoverView" customModule="Persephone" customModuleProvider="target">
<rect key="frame" x="1" y="0.0" width="200" height="17"/> <rect key="frame" x="1" y="0.0" width="43" height="42"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xgd-Cz-np3"> <imageView identifier="songCoverView" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="7Yi-vi-Frs" userLabel="Song Cover View">
<rect key="frame" x="0.0" y="2" width="322" height="14"/> <rect key="frame" x="9" y="5" width="32" height="32"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="443" id="mkA-ng-q8a"/> <constraint firstAttribute="width" constant="32" id="hhe-Vq-2aS"/>
<constraint firstAttribute="height" constant="32" id="iz9-3T-uWZ"/>
</constraints> </constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="QUEUE" id="Mqf-uh-ibl"> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kingfisher-1" id="KfD-57-Whk"/>
<font key="font" metaFont="smallSystemBold"/> <color key="contentTintColor" name="quaternaryLabelColor" catalog="System" colorSpace="catalog"/>
</imageView>
<button wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wOh-Rs-R2S" userLabel="Song Play Button">
<rect key="frame" x="9" y="5" width="32" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="cDu-pP-YAh"/>
<constraint firstAttribute="height" constant="32" id="j6D-Zt-d1I"/>
</constraints>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" imagePosition="only" alignment="center" transparent="YES" inset="2" id="eWw-vk-jay">
<behavior key="behavior" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<color key="contentTintColor" name="labelColor" catalog="System" colorSpace="catalog"/>
</button>
</subviews>
<constraints>
<constraint firstItem="wOh-Rs-R2S" firstAttribute="centerY" secondItem="5rR-Gz-AcP" secondAttribute="centerY" id="5pe-ht-AvV"/>
<constraint firstAttribute="trailing" secondItem="wOh-Rs-R2S" secondAttribute="trailing" constant="2" id="6b6-jo-ek2"/>
<constraint firstAttribute="trailing" secondItem="7Yi-vi-Frs" secondAttribute="trailing" constant="2" id="mdH-6E-1hS"/>
<constraint firstItem="7Yi-vi-Frs" firstAttribute="centerY" secondItem="5rR-Gz-AcP" secondAttribute="centerY" id="uga-Kx-ogd"/>
</constraints>
<connections>
<outlet property="queueSongButton" destination="wOh-Rs-R2S" id="tkf-l4-qKj"/>
<outlet property="queueSongCover" destination="7Yi-vi-Frs" id="fna-Ad-H3N"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="songInfoColumn" width="213" minWidth="10" maxWidth="3.4028234663852886e+38" id="HP0-ty-PFY" userLabel="Song Info">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
<font key="font" metaFont="menu" size="11"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="zb2-QK-DhK">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="songInfoCell" id="GuF-NF-B1t" userLabel="Song Info View" customClass="QueueSongInfoView" customModule="Persephone" customModuleProvider="target">
<rect key="frame" x="47" y="0.0" width="213" height="42"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tBe-Q9-3Rw" userLabel="Song Artist View">
<rect key="frame" x="1" y="7" width="219" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Song Artist" id="Ceb-ec-ydU">
<font key="font" metaFont="system" size="12"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="i0h-bn-auJ" userLabel="Song Title View">
<rect key="frame" x="1" y="23" width="211" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Song Title" id="ei8-1e-ErK">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="tBe-Q9-3Rw" secondAttribute="trailing" constant="-5" id="33u-Xt-7zG"/>
<constraint firstItem="i0h-bn-auJ" firstAttribute="leading" secondItem="GuF-NF-B1t" secondAttribute="leading" constant="3" id="Mqo-x9-boa"/>
<constraint firstAttribute="trailing" secondItem="i0h-bn-auJ" secondAttribute="trailing" constant="3" id="Qf6-8z-3ei"/>
<constraint firstItem="tBe-Q9-3Rw" firstAttribute="top" secondItem="i0h-bn-auJ" secondAttribute="bottom" id="ZRx-0N-kaR"/>
<constraint firstItem="i0h-bn-auJ" firstAttribute="top" secondItem="GuF-NF-B1t" secondAttribute="top" constant="3" id="baQ-VK-KP0"/>
<constraint firstItem="tBe-Q9-3Rw" firstAttribute="leading" secondItem="i0h-bn-auJ" secondAttribute="leading" id="uIN-3Y-iOI"/>
</constraints>
<connections>
<outlet property="queueSongArtist" destination="tBe-Q9-3Rw" id="uzL-Uq-EEl"/>
<outlet property="queueSongTitle" destination="i0h-bn-auJ" id="fQ1-z3-Jxs"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="songDurationColumn" width="64" minWidth="64" maxWidth="64" id="8O6-ox-kx2" userLabel="Duration">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
<font key="font" metaFont="menu" size="11"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="JOa-Mc-ceQ">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="songDurationCell" misplaced="YES" id="9Nz-Yf-SN1" userLabel="Song Duration View">
<rect key="frame" x="263" y="0.0" width="64" height="42"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ukg-c0-XVS">
<rect key="frame" x="8" y="13" width="41" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="42" id="HmU-DM-ORZ"/>
<constraint firstAttribute="height" constant="17" id="grB-CG-1vJ"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="right" title="88:88" id="JnJ-sF-vCP">
<font key="font" metaFont="system"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="xgd-Cz-np3" firstAttribute="leading" secondItem="GOd-cg-juD" secondAttribute="leading" constant="2" id="iOU-E2-K47"/> <constraint firstAttribute="trailing" secondItem="ukg-c0-XVS" secondAttribute="trailing" constant="10" id="jLU-Py-Sw9"/>
<constraint firstItem="xgd-Cz-np3" firstAttribute="centerY" secondItem="GOd-cg-juD" secondAttribute="centerY" id="uxd-zs-s33"/> <constraint firstItem="ukg-c0-XVS" firstAttribute="centerY" secondItem="9Nz-Yf-SN1" secondAttribute="centerY" id="jkF-3G-jYj"/>
</constraints> <constraint firstItem="ukg-c0-XVS" firstAttribute="centerX" secondItem="9Nz-Yf-SN1" secondAttribute="centerX" constant="2" id="v3t-6q-KV4"/>
</tableCellView>
<tableCellView identifier="songTitleCell" id="5rR-Gz-AcP" customClass="QueueSongTitleView" customModule="Persephone" customModuleProvider="target">
<rect key="frame" x="1" y="17" width="200" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView identifier="queuePlayerState" translatesAutoresizingMaskIntoConstraints="NO" id="o8i-cz-hIP" userLabel="Player State View">
<rect key="frame" x="3" y="-1" width="17" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="17" id="00Z-Tq-MFp"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" imageScaling="proportionallyDown" image="playButton" id="ckK-gW-Vhx"/>
</imageView>
<textField identifier="queuePosition" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mc4-Xr-oUl" userLabel="Queue Position View">
<rect key="frame" x="4" y="1" width="33" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="888." id="wpZ-1t-Do7">
<font key="font" metaFont="system"/>
<color key="textColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="i0h-bn-auJ" userLabel="Song Title View">
<rect key="frame" x="40" y="1" width="160" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="ei8-1e-ErK">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="i0h-bn-auJ" firstAttribute="leading" secondItem="o8i-cz-hIP" secondAttribute="trailing" constant="22" id="68y-un-94T"/>
<constraint firstItem="mc4-Xr-oUl" firstAttribute="centerY" secondItem="5rR-Gz-AcP" secondAttribute="centerY" id="ELP-WE-eIm"/>
<constraint firstItem="o8i-cz-hIP" firstAttribute="leading" secondItem="5rR-Gz-AcP" secondAttribute="leading" constant="3" id="SkK-PE-YOL"/>
<constraint firstAttribute="trailing" secondItem="i0h-bn-auJ" secondAttribute="trailing" constant="2" id="XQG-u9-wiY"/>
<constraint firstItem="mc4-Xr-oUl" firstAttribute="baseline" secondItem="i0h-bn-auJ" secondAttribute="baseline" id="YMz-iR-hUI"/>
<constraint firstItem="mc4-Xr-oUl" firstAttribute="leading" secondItem="5rR-Gz-AcP" secondAttribute="leading" constant="6" id="s8m-Sb-8up"/>
<constraint firstItem="o8i-cz-hIP" firstAttribute="top" secondItem="5rR-Gz-AcP" secondAttribute="top" constant="1" id="srE-Dv-Ie5"/>
</constraints> </constraints>
<connections> <connections>
<outlet property="imageView" destination="o8i-cz-hIP" id="4In-Lr-QcL"/> <outlet property="textField" destination="ukg-c0-XVS" id="FyU-zm-ijP"/>
<outlet property="queuePlayerStateImage" destination="o8i-cz-hIP" id="lUU-N4-jtd"/>
<outlet property="queuePosition" destination="mc4-Xr-oUl" id="aBD-Tg-cDt"/>
<outlet property="queueSongTitle" destination="i0h-bn-auJ" id="25v-lw-ypc"/>
<outlet property="textField" destination="i0h-bn-auJ" id="5YB-JL-2wJ"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="songArtistColumn" width="122" minWidth="64" maxWidth="1000" id="SPM-QP-DX8">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Artist">
<font key="font" metaFont="message" size="11"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="alT-Kq-P4B">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView identifier="songArtistCell" id="JSk-Vc-Y7e">
<rect key="frame" x="204" y="0.0" width="122" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="tBe-Q9-3Rw">
<rect key="frame" x="0.0" y="1" width="127" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="Ceb-ec-ydU">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="tBe-Q9-3Rw" secondAttribute="trailing" constant="-3" id="E6a-sY-dne"/>
<constraint firstItem="tBe-Q9-3Rw" firstAttribute="leading" secondItem="JSk-Vc-Y7e" secondAttribute="leading" constant="2" id="Gm4-l1-WRz"/>
<constraint firstItem="tBe-Q9-3Rw" firstAttribute="centerY" secondItem="JSk-Vc-Y7e" secondAttribute="centerY" id="KhJ-nn-rh5"/>
</constraints>
<connections>
<outlet property="textField" destination="tBe-Q9-3Rw" id="2e6-zi-tKj"/>
</connections> </connections>
</tableCellView> </tableCellView>
</prototypeCellViews> </prototypeCellViews>
@ -797,7 +821,7 @@
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="500" id="zuT-k9-w8d"/> <constraint firstAttribute="width" relation="lessThanOrEqual" constant="500" id="zuT-k9-w8d"/>
</constraints> </constraints>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="7mx-v9-DSr"> <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="7mx-v9-DSr">
<rect key="frame" x="0.0" y="237" width="328" height="16"/> <rect key="frame" x="0.0" y="201" width="329" height="16"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</scroller> </scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="p5z-C0-FUJ"> <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="p5z-C0-FUJ">
@ -806,11 +830,11 @@
</scroller> </scroller>
</scrollView> </scrollView>
<customView misplaced="YES" id="iUb-eV-Qws"> <customView misplaced="YES" id="iUb-eV-Qws">
<rect key="frame" x="0.0" y="220" width="328" height="327"/> <rect key="frame" x="0.0" y="218" width="329" height="325"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Dw3-M5-tWY" customClass="CurrentCoverArtView" customModule="Persephone" customModuleProvider="target"> <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Dw3-M5-tWY" customClass="CurrentCoverArtView" customModule="Persephone" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="328" height="328"/> <rect key="frame" x="0.0" y="0.0" width="329" height="329"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="defaultCoverArt" id="IoN-3N-TCb"/> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="defaultCoverArt" id="IoN-3N-TCb"/>
</imageView> </imageView>
</subviews> </subviews>
@ -851,7 +875,7 @@
</items> </items>
</menu> </menu>
</objects> </objects>
<point key="canvasLocation" x="825" y="746"/> <point key="canvasLocation" x="824.5" y="745.5"/>
</scene> </scene>
<!--Album View Controller--> <!--Album View Controller-->
<scene sceneID="7Ua-Hj-zWt"> <scene sceneID="7Ua-Hj-zWt">
@ -920,6 +944,7 @@
<image name="NSPreferencesGeneral" width="32" height="32"/> <image name="NSPreferencesGeneral" width="32" height="32"/>
<image name="coverArtPreferencesIcon" width="32" height="32"/> <image name="coverArtPreferencesIcon" width="32" height="32"/>
<image name="defaultCoverArt" width="128" height="128"/> <image name="defaultCoverArt" width="128" height="128"/>
<image name="kingfisher-1" width="250" height="250"/>
<image name="nextTrackButton" width="17" height="17"/> <image name="nextTrackButton" width="17" height="17"/>
<image name="playButton" width="17" height="17"/> <image name="playButton" width="17" height="17"/>
<image name="prevTrackButton" width="17" height="17"/> <image name="prevTrackButton" width="17" height="17"/>

View File

@ -10,4 +10,5 @@ struct DraggedSong: Codable {
var type: DraggedSongType var type: DraggedSongType
var title: String? var title: String?
var artist: String? var artist: String?
var cover: String?
} }

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.