diff --git a/Persephone.xcodeproj/project.pbxproj b/Persephone.xcodeproj/project.pbxproj index 300c183..7f066c9 100644 --- a/Persephone.xcodeproj/project.pbxproj +++ b/Persephone.xcodeproj/project.pbxproj @@ -49,6 +49,7 @@ E43B67AA22909793007DCF55 /* AlbumDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B67A822909793007DCF55 /* AlbumDetailView.swift */; }; E43B67AB22909793007DCF55 /* AlbumDetailView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E43B67A922909793007DCF55 /* AlbumDetailView.xib */; }; E43B67AD229194CD007DCF55 /* AlbumTracksDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B67AC229194CD007DCF55 /* AlbumTracksDataSource.swift */; }; + E43BECA0238835DC00CAF1EB /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = E43BEC9F238835DC00CAF1EB /* Kingfisher */; }; E4405192227644340090CD6F /* MPDServerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4405191227644340090CD6F /* MPDServerController.swift */; }; E44051942278765A0090CD6F /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = E44051932278765A0090CD6F /* App.swift */; }; E440519C227BAF2E0090CD6F /* UIActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519B227BAF2E0090CD6F /* UIActions.swift */; }; @@ -330,6 +331,7 @@ E4B11BA72274E4500075461B /* libmpdclient.2.dylib in Frameworks */, E49A5485233E5ADC00EED353 /* Differ in Frameworks */, E4677C48233E60E70041474F /* MediaKeyTap in Frameworks */, + E43BECA0238835DC00CAF1EB /* Kingfisher in Frameworks */, E49A548E233E5B6000EED353 /* SwiftyJSON in Frameworks */, E4E96D13233E630800AFD36F /* PMKFoundation in Frameworks */, E49A5482233E580800EED353 /* PromiseKit in Frameworks */, @@ -446,9 +448,9 @@ E41E5302223BF9C300173814 /* MPDClient+Idle.swift */, E41E5300223BF99300173814 /* MPDClient+Queue.swift */, E42A4D5022E2167E001C6CAD /* MPDClient+Songs.swift */, + E408D3BD220E03EE0006D9BE /* RawRepresentable.swift */, E41E5306223C019100173814 /* MPDClient+Status.swift */, E41E52FE223BF95E00173814 /* MPDClient+Transport.swift */, - E408D3BD220E03EE0006D9BE /* RawRepresentable.swift */, ); path = Extensions; sourceTree = ""; @@ -765,6 +767,7 @@ E49A548D233E5B6000EED353 /* SwiftyJSON */, E4677C47233E60E70041474F /* MediaKeyTap */, E4E96D12233E630800AFD36F /* PMKFoundation */, + E43BEC9F238835DC00CAF1EB /* Kingfisher */, ); productName = Persephone; productReference = E40786182110CE6E006887B1 /* Persephone.app */; @@ -857,6 +860,7 @@ E49A548C233E5B6000EED353 /* XCRemoteSwiftPackageReference "SwiftyJSON" */, E4A9BEF9233E5F9000457785 /* XCRemoteSwiftPackageReference "MediaKeyTap" */, E4E96D11233E630800AFD36F /* XCRemoteSwiftPackageReference "Foundation" */, + E43BEC9E238835DC00CAF1EB /* XCRemoteSwiftPackageReference "Kingfisher" */, ); productRefGroup = E40786192110CE6E006887B1 /* Products */; projectDirPath = ""; @@ -1385,6 +1389,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + E43BEC9E238835DC00CAF1EB /* XCRemoteSwiftPackageReference "Kingfisher" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/onevcat/Kingfisher.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.10.1; + }; + }; E49A5480233E580800EED353 /* XCRemoteSwiftPackageReference "PromiseKit" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/mxcl/PromiseKit"; @@ -1444,6 +1456,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + E43BEC9F238835DC00CAF1EB /* Kingfisher */ = { + isa = XCSwiftPackageProductDependency; + package = E43BEC9E238835DC00CAF1EB /* XCRemoteSwiftPackageReference "Kingfisher" */; + productName = Kingfisher; + }; E4677C47233E60E70041474F /* MediaKeyTap */ = { isa = XCSwiftPackageProductDependency; package = E4A9BEF9233E5F9000457785 /* XCRemoteSwiftPackageReference "MediaKeyTap" */; diff --git a/Persephone.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Persephone.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6bea6d9..1fa0f80 100644 --- a/Persephone.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Persephone.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -28,6 +28,15 @@ "version": "3.3.3" } }, + { + "package": "Kingfisher", + "repositoryURL": "https://github.com/onevcat/Kingfisher.git", + "state": { + "branch": null, + "revision": "8ef6ca8b1b767ac2400762ed2f2bf75ddea3de5b", + "version": "5.10.1" + } + }, { "package": "MediaKeyTap", "repositoryURL": "https://github.com/danbee/MediaKeyTap", diff --git a/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift b/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift index 50d4b12..2c14339 100644 --- a/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift +++ b/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift @@ -23,24 +23,6 @@ class AlbumDataSource: NSObject, NSCollectionViewDataSource { albumViewItem.view.wantsLayer = true albumViewItem.setAlbum(albums[indexPath.item]) - switch albums[indexPath.item].coverArt { - case .notLoaded: - let album = albums[indexPath.item] - guard let path = album.mpdAlbum.path else { break } - - CoverArtService(path: path, album: album) - .fetchCoverArt() - .done { image in - DispatchQueue.main.async { - App.store.dispatch( - UpdateCoverArtAction(coverArt: image, albumIndex: indexPath.item) - ) - } - } - default: - break - } - return albumViewItem } } diff --git a/Persephone/Components/Browser/Album Browser/AlbumViewItem.swift b/Persephone/Components/Browser/Album Browser/AlbumViewItem.swift index cbbf9d8..c00bf91 100644 --- a/Persephone/Components/Browser/Album Browser/AlbumViewItem.swift +++ b/Persephone/Components/Browser/Album Browser/AlbumViewItem.swift @@ -7,11 +7,24 @@ // import AppKit +import Kingfisher class AlbumViewItem: NSCollectionViewItem { var observer: NSKeyValueObservation? var album: Album? + var coverArtFilenames: [String] { + return [ + "folder.jpg", + "cover.jpg", + "\(album?.artist ?? "") - \(album?.title ?? "").jpg" + ] + } + + var musicDir: String { + return App.store.state.preferencesState.expandedMpdLibraryDir + } + override var isSelected: Bool { didSet { setAppearance(selected: isSelected) @@ -50,13 +63,31 @@ class AlbumViewItem: NSCollectionViewItem { self.album = album albumTitle.stringValue = album.title albumArtist.stringValue = album.artist + setAlbumCover(album) + } - switch album.coverArt { - case .loaded(let coverArt): - albumCoverView.image = coverArt ?? .defaultCoverArt - default: - albumCoverView.image = .defaultCoverArt - } + func setAlbumCover(_ album: Album) { + guard let imagePath = fileSystemArtworkFilePath() else { return } + + let imageURL = URL(fileURLWithPath: imagePath) + let provider = LocalFileImageDataProvider(fileURL: imageURL) + albumCoverView.kf.setImage( + with: .provider(provider), + placeholder: NSImage.defaultCoverArt, + options: [ + .processor(DownsamplingImageProcessor(size: NSSize(width: 180, height: 180))), + .scaleFactor(2), + ] + ) + } + + func fileSystemArtworkFilePath() -> String? { + return self.coverArtFilenames + .lazy + .map { "\(self.musicDir)/\(self.album?.mpdAlbum.path ?? "")/\($0)" } + .first { + FileManager.default.fileExists(atPath: $0) + } } func setAppearance(selected isSelected: Bool) { diff --git a/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift b/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift index 0940d93..41b2977 100644 --- a/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift +++ b/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift @@ -54,13 +54,6 @@ class AlbumDetailView: NSViewController { albumTitle.stringValue = album.title albumMetadata.stringValue = "\(album.artist) ยท \(date)" - switch album.coverArt { - case .loaded(let coverArt): - albumCoverView.image = coverArt ?? .defaultCoverArt - default: - albumCoverView.image = .defaultCoverArt - } - super.viewWillAppear() } diff --git a/Persephone/Models/Album.swift b/Persephone/Models/Album.swift index 9967802..f3d3380 100644 --- a/Persephone/Models/Album.swift +++ b/Persephone/Models/Album.swift @@ -11,7 +11,6 @@ import CryptoSwift struct Album { var mpdAlbum: MPDClient.MPDAlbum - var coverArt: Loading = .notLoaded init(mpdAlbum: MPDClient.MPDAlbum) { self.mpdAlbum = mpdAlbum @@ -37,7 +36,6 @@ struct Album { extension Album: Equatable { static func == (lhs: Album, rhs: Album) -> Bool { - return (lhs.mpdAlbum == rhs.mpdAlbum) && - (lhs.coverArt ~= rhs.coverArt) + return (lhs.mpdAlbum == rhs.mpdAlbum) } } diff --git a/Persephone/State/Reducers/AlbumListReducer.swift b/Persephone/State/Reducers/AlbumListReducer.swift index f97a7ff..c710e28 100644 --- a/Persephone/State/Reducers/AlbumListReducer.swift +++ b/Persephone/State/Reducers/AlbumListReducer.swift @@ -16,21 +16,10 @@ func albumListReducer(action: Action, state: AlbumListState?) -> AlbumListState state.albums = action.albums.map { Album(mpdAlbum: $0) } case let action as UpdateCoverArtAction: - state.albums[action.albumIndex].coverArt = .loaded(action.coverArt) + break case is ResetAlbumListCoverArtAction: - state.albums = state.albums.map { - var album = $0 - switch album.coverArt { - case .loaded(let coverArt): - if coverArt == nil { - album.coverArt = .notLoaded - } - default: - album.coverArt = .notLoaded - } - return album - } + break default: break