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

Mostly working, albumlist is not showing album art

This commit is contained in:
Daniel Barber 2019-04-27 15:09:24 -04:00
parent bb5a7c2c5c
commit 2e6c903d74
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
21 changed files with 264 additions and 191 deletions

View File

@ -88,6 +88,10 @@
E4B11B6F226A5C7A0075461B /* UpdateStatusAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B6E226A5C7A0075461B /* UpdateStatusAction.swift */; };
E4B11B71226A64E60075461B /* UpdateElapsedTimeAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B70226A64E60075461B /* UpdateElapsedTimeAction.swift */; };
E4B11B73226A6C770075461B /* TrackTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B72226A6C770075461B /* TrackTimer.swift */; };
E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B74226CC4D30075461B /* QueueReducer.swift */; };
E4B11B77226CC6BE0075461B /* UpdateQueuePosAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B76226CC6BE0075461B /* UpdateQueuePosAction.swift */; };
E4B11B79226D346B0075461B /* AlbumListReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B78226D346B0075461B /* AlbumListReducer.swift */; };
E4B11B7B226D34F80075461B /* UpdateAlbumListAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B11B7A226D34F80075461B /* UpdateAlbumListAction.swift */; };
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */; };
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C8B53D22349002009A20F3 /* MPDIdle.swift */; };
E4E8CC902204EC7F0024217A /* Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E8CC8F2204EC7F0024217A /* Delegate.swift */; };
@ -267,6 +271,10 @@
E4B11B6E226A5C7A0075461B /* UpdateStatusAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateStatusAction.swift; sourceTree = "<group>"; };
E4B11B70226A64E60075461B /* UpdateElapsedTimeAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateElapsedTimeAction.swift; sourceTree = "<group>"; };
E4B11B72226A6C770075461B /* TrackTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackTimer.swift; sourceTree = "<group>"; };
E4B11B74226CC4D30075461B /* QueueReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueReducer.swift; sourceTree = "<group>"; };
E4B11B76226CC6BE0075461B /* UpdateQueuePosAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateQueuePosAction.swift; sourceTree = "<group>"; };
E4B11B78226D346B0075461B /* AlbumListReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumListReducer.swift; sourceTree = "<group>"; };
E4B11B7A226D34F80075461B /* UpdateAlbumListAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateAlbumListAction.swift; sourceTree = "<group>"; };
E4C8B53B22342005009A20F3 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
E4C8B53D22349002009A20F3 /* MPDIdle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDIdle.swift; sourceTree = "<group>"; };
E4E8CC8F2204EC7F0024217A /* Delegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Delegate.swift; sourceTree = "<group>"; };
@ -566,6 +574,8 @@
children = (
E4B11B60226A4BFF0075461B /* PlayerReducer.swift */,
E4B11B62226A4C510075461B /* AppReducer.swift */,
E4B11B74226CC4D30075461B /* QueueReducer.swift */,
E4B11B78226D346B0075461B /* AlbumListReducer.swift */,
);
path = Reducers;
sourceTree = "<group>";
@ -584,9 +594,11 @@
E4B11B6B226A5AF50075461B /* Actions */ = {
isa = PBXGroup;
children = (
E4B11B6C226A5B180075461B /* UpdateQueueAction.swift */,
E4B11B6E226A5C7A0075461B /* UpdateStatusAction.swift */,
E4B11B7A226D34F80075461B /* UpdateAlbumListAction.swift */,
E4B11B70226A64E60075461B /* UpdateElapsedTimeAction.swift */,
E4B11B6C226A5B180075461B /* UpdateQueueAction.swift */,
E4B11B76226CC6BE0075461B /* UpdateQueuePosAction.swift */,
E4B11B6E226A5C7A0075461B /* UpdateStatusAction.swift */,
);
path = Actions;
sourceTree = "<group>";
@ -837,6 +849,7 @@
E4F6B467221E233200ACF42A /* AlbumDataSource.swift in Sources */,
E408D3C2220E134F0006D9BE /* AlbumViewController.swift in Sources */,
E40FE71B221B904300A4223F /* NSEvent.swift in Sources */,
E4B11B7B226D34F80075461B /* UpdateAlbumListAction.swift in Sources */,
E4B11B6D226A5B180075461B /* UpdateQueueAction.swift in Sources */,
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */,
@ -848,6 +861,7 @@
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */,
E41E5310223EF6CE00173814 /* AlbumArtService+Remote.swift in Sources */,
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */,
E4B11B77226CC6BE0075461B /* UpdateQueuePosAction.swift in Sources */,
E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */,
E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */,
E47E2FD72220720300F747E6 /* AlbumItemView.swift in Sources */,
@ -870,8 +884,10 @@
E419E2872249B96600216A8C /* Song.swift in Sources */,
E439109822640213002982E9 /* SongNotifierService.swift in Sources */,
E407861C2110CE6E006887B1 /* AppDelegate.swift in Sources */,
E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */,
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */,
E4B11B73226A6C770075461B /* TrackTimer.swift in Sources */,
E4B11B79226D346B0075461B /* AlbumListReducer.swift in Sources */,
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */,
E41E52FF223BF95E00173814 /* MPDClient+Transport.swift in Sources */,
E47E2FD322205D2500F747E6 /* MainWindow.swift in Sources */,

View File

@ -0,0 +1,13 @@
//
// UpdateAlbumListAction.swift
// Persephone
//
// Created by Daniel Barber on 2019/4/21.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
struct UpdateAlbumListAction: Action {
var albums: [MPDClient.MPDAlbum]
}

View File

@ -0,0 +1,13 @@
//
// UpdateQueuePosAction.swift
// Persephone
//
// Created by Daniel Barber on 2019/4/21.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
struct UpdateQueuePosAction: Action {
var queuePos: Int
}

View File

@ -21,7 +21,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
static let trackTimer = TrackTimer()
static let store = Store(reducer: appReducer, state: nil)
static let store = Store<AppState>(reducer: appReducer, state: nil)
func applicationDidFinishLaunching(_ aNotification: Notification) {
connect()

View File

@ -7,10 +7,14 @@
//
import Cocoa
import ReSwift
class AlbumViewController: NSViewController,
NSCollectionViewDelegate,
NSCollectionViewDelegateFlowLayout {
NSCollectionViewDelegateFlowLayout,
StoreSubscriber {
typealias StoreSubscriberStateType = AlbumListState
var preferences = Preferences()
let paddingWidth: CGFloat = 40
@ -21,22 +25,14 @@ class AlbumViewController: NSViewController,
override func viewDidLoad() {
super.viewDidLoad()
AppDelegate.store.subscribe(self) {
(subscription: Subscription<AppState>) -> Subscription<AlbumListState> in
subscription.select { state -> AlbumListState in state.albumListState }
}
albumScrollView.postsBoundsChangedNotifications = true
NotificationCenter.default.addObserver(
self,
selector: #selector(updateAlbums(_:)),
name: Notification.loadedAlbums,
object: AppDelegate.mpdClient
)
NotificationCenter.default.addObserver(
self,
selector: #selector(clearAlbums(_:)),
name: Notification.willDisconnect,
object: AppDelegate.mpdClient
)
albumCollectionView.dataSource = dataSource
preferences.addObserver(self, forKeyPath: "mpdLibraryDir")
@ -72,24 +68,15 @@ class AlbumViewController: NSViewController,
case "mpdLibraryDir":
albumCollectionView.reloadData()
case "fetchMissingArtworkFromInternet":
dataSource.resetCoverArt()
// dataSource.resetCoverArt()
albumCollectionView.reloadData()
default:
break
}
}
@objc func updateAlbums(_ notification: Notification) {
guard let albums = notification.userInfo?[Notification.albumsKey] as? [MPDClient.MPDAlbum]
else { return }
dataSource.albums = albums.map { Album(mpdAlbum: $0) }
albumCollectionView.reloadData()
}
@objc func clearAlbums(_ notification: Notification) {
dataSource.albums = []
func newState(state: StoreSubscriberStateType) {
print("New album list state")
albumCollectionView.reloadData()
}

View File

@ -16,26 +16,16 @@ class NotificationsController: MPDClientDelegate {
}
func willDisconnect(mpdClient: MPDClient) {
DispatchQueue.main.async {
AppDelegate.store.dispatch(UpdateAlbumListAction(albums: []))
}
sendNotification(name: Notification.willDisconnect)
}
func didUpdateStatus(mpdClient: MPDClient, status: MPDClient.MPDStatus) {
AppDelegate.store.dispatch(UpdateStatusAction(status: status))
sendNotification(
name: Notification.stateChanged,
userInfo: [Notification.stateKey: status.state]
)
sendNotification(
name: Notification.timeChanged,
userInfo: [
Notification.totalTimeKey: status.totalTime,
Notification.elapsedTimeMsKey: status.elapsedTimeMs
]
)
}
func didUpdateTime(mpdClient: MPDClient, total: UInt, elapsedMs: UInt) {
DispatchQueue.main.async {
AppDelegate.store.dispatch(UpdateStatusAction(status: status))
}
}
func willStartDatabaseUpdate(mpdClient: MPDClient) {
@ -47,21 +37,22 @@ class NotificationsController: MPDClientDelegate {
}
func didUpdateQueue(mpdClient: MPDClient, queue: [MPDClient.MPDSong]) {
//AppDelegate.store.dispatch(UpdateQueueAction(queue: queue))
sendNotification(
name: Notification.queueChanged,
userInfo: [Notification.queueKey: queue]
)
DispatchQueue.main.async {
AppDelegate.store.dispatch(UpdateQueueAction(queue: queue))
}
}
func didUpdateQueuePos(mpdClient: MPDClient, song: Int) {
sendNotification(
name: Notification.queuePosChanged,
userInfo: [Notification.queuePosKey: song]
)
DispatchQueue.main.async {
AppDelegate.store.dispatch(UpdateQueuePosAction(queuePos: song))
}
}
func didLoadAlbums(mpdClient: MPDClient, albums: [MPDClient.MPDAlbum]) {
print("Albums")
DispatchQueue.main.async {
AppDelegate.store.dispatch(UpdateAlbumListAction(albums: albums))
}
sendNotification(
name: Notification.loadedAlbums,
userInfo: [Notification.albumsKey: albums]

View File

@ -7,10 +7,13 @@
//
import Cocoa
import PromiseKit
import ReSwift
class QueueViewController: NSViewController,
NSOutlineViewDelegate {
NSOutlineViewDelegate,
StoreSubscriber {
typealias StoreSubscriberStateType = QueueState
var dataSource = QueueDataSource()
@IBOutlet var queueView: NSOutlineView!
@ -19,11 +22,22 @@ class QueueViewController: NSViewController,
override func viewDidLoad() {
super.viewDidLoad()
setupNotificationObservers()
AppDelegate.store.subscribe(self) {
(subscription: Subscription<AppState>) -> Subscription<QueueState> in
subscription.select { state in state.queueState }
}
queueView.dataSource = dataSource
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
}
}
func newState(state: StoreSubscriberStateType) {
print("New queue state")
dataSource.setQueueIcon()
queueView.reloadData()
updateAlbumArt(state)
}
override func keyDown(with event: NSEvent) {
switch event.keyCode {
@ -42,15 +56,8 @@ class QueueViewController: NSViewController,
}
}
@objc func stateChanged(_ notification: Notification) {
guard let state = notification.userInfo?[Notification.stateKey] as? MPDClient.MPDStatus.State
else { return }
dataSource.setQueueIcon(state)
}
func notifyTrack() {
guard let currentSong = dataSource.currentSong,
func notifyTrack(_ state: QueueState) {
guard let currentSong = state.currentSong,
let status = AppDelegate.mpdClient.status,
status.state == .playing
else { return }
@ -59,25 +66,10 @@ class QueueViewController: NSViewController,
.deliver()
}
@objc func queueChanged(_ notification: Notification) {
guard let queue = notification.userInfo?[Notification.queueKey] as? [MPDClient.MPDSong]
else { return }
dataSource.updateQueue(queue)
queueView.reloadData()
}
@objc func queuePosChanged(_ notification: Notification) {
guard let queuePos = notification.userInfo?[Notification.queuePosKey] as? Int
else { return }
dataSource.setQueuePos(queuePos)
queueView.reloadData()
updateAlbumArt()
}
func updateAlbumArt() {
if let playingQueueItem = dataSource.queue.first(where: { $0.isPlaying }) {
func updateAlbumArt(_ state: QueueState) {
if let playingQueueItem = state.queue.first(
where: { $0.isPlaying }
) {
let albumArtService = AlbumArtService(song: playingQueueItem.song)
albumArtService.fetchBigAlbumArt()
@ -88,7 +80,7 @@ class QueueViewController: NSViewController,
self.queueAlbumArtImage.image = NSImage.defaultCoverArt
}
self.notifyTrack()
self.notifyTrack(state)
}
.cauterize()
} else {
@ -168,27 +160,4 @@ func cellForSongTitle(_ outlineView: NSOutlineView, with queueItem: QueueItem) -
return cellView
}
func setupNotificationObservers() {
NotificationCenter.default.addObserver(
self,
selector: #selector(stateChanged(_:)),
name: Notification.stateChanged,
object: AppDelegate.mpdClient
)
NotificationCenter.default.addObserver(
self,
selector: #selector(queueChanged(_:)),
name: Notification.queueChanged,
object: AppDelegate.mpdClient
)
NotificationCenter.default.addObserver(
self,
selector: #selector(queuePosChanged(_:)),
name: Notification.queuePosChanged,
object: AppDelegate.mpdClient
)
}
}

View File

@ -10,7 +10,7 @@ import Cocoa
import ReSwift
class WindowController: NSWindowController, StoreSubscriber {
typealias StoreSubscriberStateType = AppState
typealias StoreSubscriberStateType = PlayerState
enum TransportAction: Int {
case prevTrack, playPause, stop, nextTrack
@ -23,8 +23,11 @@ class WindowController: NSWindowController, StoreSubscriber {
super.windowDidLoad()
window?.titleVisibility = .hidden
// TODO: We will want to filter this subscribe later
AppDelegate.store.subscribe(self)
AppDelegate.store.subscribe(self) {
(subscription: Subscription<AppState>) -> Subscription<PlayerState> in
subscription.select { state in state.playerState }
}
NotificationCenter.default.addObserver(
self,
@ -44,12 +47,13 @@ class WindowController: NSWindowController, StoreSubscriber {
trackRemaining.font = .timerFont
}
func newState(state: WindowController.StoreSubscriberStateType) {
self.state = state.playerState.state
func newState(state: StoreSubscriberStateType) {
print("New player state")
self.state = state.state
DispatchQueue.main.async {
self.setTransportControlState(state.playerState)
self.setTrackProgressControls(state.playerState)
self.setTransportControlState(state)
self.setTrackProgressControls(state)
}
}

View File

@ -10,45 +10,44 @@ import Cocoa
import PromiseKit
class AlbumDataSource: NSObject, NSCollectionViewDataSource {
var albums: [Album] = []
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return albums.count
}
func resetCoverArt() {
albums = albums.map {
var album = $0
album.coverArtFetched = false
return album
}
return AppDelegate.store.state.albumListState.albums.count
}
//
// func resetCoverArt() {
// albums = AppDelegate.store.state.albumListState.albums.map {
// var album = $0
// album.coverArtFetched = false
// return album
// }
// }
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let albums = AppDelegate.store.state.albumListState.albums
let item = collectionView.makeItem(withIdentifier: .albumViewItem, for: indexPath)
guard let albumViewItem = item as? AlbumViewItem else { return item }
albumViewItem.view.wantsLayer = true
albumViewItem.setAlbum(albums[indexPath.item])
if albums[indexPath.item].coverArt == nil &&
!albums[indexPath.item].coverArtFetched {
AppDelegate.mpdClient.getAlbumFirstSong(for: albums[indexPath.item].mpdAlbum) {
guard let song = $0 else { return }
AlbumArtService(song: Song(mpdSong: song))
.fetchAlbumArt()
.done { image in
self.albums[indexPath.item].coverArt = image
self.albums[indexPath.item].coverArtFetched = true
DispatchQueue.main.async {
collectionView.reloadItems(at: [indexPath])
}
}
}
}
// if albums[indexPath.item].coverArt == nil &&
// !albums[indexPath.item].coverArtFetched {
//
// AppDelegate.mpdClient.getAlbumFirstSong(for: albums[indexPath.item].mpdAlbum) {
// guard let song = $0 else { return }
//
// AlbumArtService(song: Song(mpdSong: song))
// .fetchAlbumArt()
// .done { image in
// self.albums[indexPath.item].coverArt = image
// self.albums[indexPath.item].coverArtFetched = true
//
// DispatchQueue.main.async {
// collectionView.reloadItems(at: [indexPath])
// }
// }
// }
// }
return albumViewItem
}

View File

@ -9,46 +9,13 @@
import Cocoa
class QueueDataSource: NSObject, NSOutlineViewDataSource {
var queue: [QueueItem] = []
var queuePos: Int = -1
var currentSong: Song?
var queueIcon: NSImage? = nil
func updateQueue(_ queue: [MPDClient.MPDSong]) {
queuePos = -1
self.queue = queue.enumerated().map { index, mpdSong in
let song = Song(mpdSong: mpdSong)
return QueueItem(
song: song,
queuePos: index,
isPlaying: index == queuePos
)
}
}
func setQueuePos(_ queuePos: Int) {
let oldSongRowPos = self.queuePos
let newSongRowPos = queuePos
self.queuePos = queuePos
if oldSongRowPos >= 0 {
queue[oldSongRowPos].isPlaying = false
}
if newSongRowPos >= 0 {
queue[newSongRowPos].isPlaying = true
currentSong = queue[newSongRowPos].song
} else {
currentSong = nil
}
}
func setQueueIcon(_ state: MPDClient.MPDStatus.State) {
switch state {
case .playing:
func setQueueIcon() {
switch AppDelegate.store.state.playerState.state {
case .playing?:
queueIcon = .playIcon
case .paused:
case .paused?:
queueIcon = .pauseIcon
default:
queueIcon = nil
@ -56,7 +23,7 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
}
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
return queue.count + 1
return AppDelegate.store.state.queueState.queue.count + 1
}
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
@ -65,7 +32,7 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
if index > 0 {
return queue[index - 1]
return AppDelegate.store.state.queueState.queue[index - 1]
} else {
return false
}

View File

@ -30,3 +30,10 @@ struct Album {
return "\(title) - \(artist)".sha1()
}
}
extension Album: Equatable {
static func == (lhs: Album, rhs: Album) -> Bool {
return (lhs.artist == rhs.artist) &&
(lhs.title == rhs.title)
}
}

View File

@ -13,3 +13,11 @@ struct QueueItem {
var queuePos: Int
var isPlaying: Bool
}
extension QueueItem: Equatable {
static func == (lhs: QueueItem, rhs: QueueItem) -> Bool {
return (lhs.song == rhs.song) &&
(lhs.queuePos == rhs.queuePos) &&
(lhs.isPlaying == rhs.isPlaying)
}
}

View File

@ -23,3 +23,11 @@ struct Song {
return Album(mpdAlbum: mpdSong.album)
}
}
extension Song: Equatable {
static func == (lhs: Song, rhs: Song) -> Bool {
return (lhs.title == rhs.title) &&
(lhs.artist == rhs.artist) &&
(lhs.album == rhs.album)
}
}

View File

@ -21,7 +21,7 @@ class TrackTimer: NSObject {
startTime = CACurrentMediaTime()
startElapsed = Double(elapsedTimeMs) / 1000
DispatchQueue.main.sync {
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(
withTimeInterval: 0.25,
repeats: true

View File

@ -0,0 +1,22 @@
//
// AlbumListReducer.swift
// Persephone
//
// Created by Daniel Barber on 2019/4/21.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
func albumListReducer(action: Action, state: AlbumListState?) -> AlbumListState {
var state = state ?? AlbumListState()
switch action {
case let action as UpdateAlbumListAction:
state.albums = action.albums.map { Album(mpdAlbum: $0) }
default:
break
}
return state
}

View File

@ -6,11 +6,13 @@
// Copyright © 2019 Dan Barber. All rights reserved.
//
import Foundation
import ReSwift
func appReducer(action: Action, state: AppState?) -> AppState {
print(action)
return AppState(
playerState: playerReducer(action: action, state: state?.playerState)
playerState: playerReducer(action: action, state: state?.playerState),
queueState: queueReducer(action: action, state: state?.queueState),
albumListState: albumListReducer(action: action, state: state?.albumListState)
)
}

View File

@ -0,0 +1,45 @@
//
// QueueReducer.swift
// Persephone
//
// Created by Daniel Barber on 2019/4/21.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
func queueReducer(action: Action, state: QueueState?) -> QueueState {
var state = state ?? QueueState()
switch action {
case let action as UpdateQueueAction:
state.queuePos = -1
state.queue = action.queue.enumerated().map { index, mpdSong in
let song = Song(mpdSong: mpdSong)
return QueueItem(
song: song,
queuePos: index,
isPlaying: index == state.queuePos
)
}
case let action as UpdateQueuePosAction:
let oldSongRowPos = state.queuePos
let newSongRowPos = action.queuePos
state.queuePos = action.queuePos
if oldSongRowPos >= 0 {
state.queue[oldSongRowPos].isPlaying = false
}
if newSongRowPos >= 0 {
state.queue[newSongRowPos].isPlaying = true
}
default:
break
}
return state
}

View File

@ -10,4 +10,11 @@ import ReSwift
struct AlbumListState: StateType {
var albums: [Album] = []
var albumsWithUpdates: [Int]
}
extension AlbumListState: Equatable {
static func == (lhs: AlbumListState, rhs: AlbumListState) -> Bool {
return lhs.albums == rhs.albums
}
}

View File

@ -10,6 +10,6 @@ import ReSwift
struct AppState: StateType {
var playerState = PlayerState()
// var queueState = QueueState()
// var albumListState = AlbumListState()
var queueState = QueueState()
var albumListState = AlbumListState()
}

View File

@ -17,3 +17,11 @@ struct PlayerState: StateType {
var totalTime: UInt?
var elapsedTimeMs: UInt?
}
extension PlayerState: Equatable {
static func == (lhs: PlayerState, rhs: PlayerState) -> Bool {
return (lhs.state == rhs.state) &&
(lhs.totalTime == rhs.totalTime) &&
(lhs.elapsedTimeMs == rhs.elapsedTimeMs)
}
}

View File

@ -12,3 +12,10 @@ struct QueueState: StateType {
var queue: [QueueItem] = []
var queuePos: Int = -1
}
extension QueueState: Equatable {
static func == (lhs: QueueState, rhs: QueueState) -> Bool {
return (lhs.queue == rhs.queue) &&
(lhs.queuePos == rhs.queuePos)
}
}