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

Handle closing and opening windows

This commit is contained in:
Daniel Barber 2019-05-02 22:32:20 -04:00
parent e6bbe4f35d
commit 49269ca21b
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
15 changed files with 128 additions and 64 deletions

View File

@ -43,6 +43,9 @@
E4405196227879960090CD6F /* MPDActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4405195227879960090CD6F /* MPDActions.swift */; };
E440519822787CB40090CD6F /* MPDState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519722787CB40090CD6F /* MPDState.swift */; };
E440519A22787CF60090CD6F /* MPDReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519922787CF60090CD6F /* MPDReducer.swift */; };
E440519C227BAF2E0090CD6F /* UIActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519B227BAF2E0090CD6F /* UIActions.swift */; };
E440519E227BB0720090CD6F /* UIReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519D227BB0720090CD6F /* UIReducer.swift */; };
E44051A0227BB0AB0090CD6F /* UIState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E440519F227BB0AB0090CD6F /* UIState.swift */; };
E450AD7E222620A10091BED3 /* Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = E450AD7D222620A10091BED3 /* Album.swift */; };
E450AD8F22262C620091BED3 /* PromiseKit.framework.dSYM in Resources */ = {isa = PBXBuildFile; fileRef = E450AD8E22262C620091BED3 /* PromiseKit.framework.dSYM */; };
E450AD9122262C780091BED3 /* SwiftyJSON.framework.dSYM in Resources */ = {isa = PBXBuildFile; fileRef = E450AD9022262C780091BED3 /* SwiftyJSON.framework.dSYM */; };
@ -245,6 +248,9 @@
E4405195227879960090CD6F /* MPDActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDActions.swift; sourceTree = "<group>"; };
E440519722787CB40090CD6F /* MPDState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDState.swift; sourceTree = "<group>"; };
E440519922787CF60090CD6F /* MPDReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDReducer.swift; sourceTree = "<group>"; };
E440519B227BAF2E0090CD6F /* UIActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIActions.swift; sourceTree = "<group>"; };
E440519D227BB0720090CD6F /* UIReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIReducer.swift; sourceTree = "<group>"; };
E440519F227BB0AB0090CD6F /* UIState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIState.swift; sourceTree = "<group>"; };
E450AD7D222620A10091BED3 /* Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Album.swift; sourceTree = "<group>"; };
E450AD8522262AE60091BED3 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/Mac/SwiftyJSON.framework; sourceTree = "<group>"; };
E450AD8C22262C590091BED3 /* PromiseKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PromiseKit.framework; path = Carthage/Build/Mac/PromiseKit.framework; sourceTree = "<group>"; };
@ -603,6 +609,7 @@
E4B11B78226D346B0075461B /* AlbumListReducer.swift */,
E4FF718F227601B400D4C412 /* PreferencesReducer.swift */,
E440519922787CF60090CD6F /* MPDReducer.swift */,
E440519D227BB0720090CD6F /* UIReducer.swift */,
);
path = Reducers;
sourceTree = "<group>";
@ -613,6 +620,7 @@
E4B11B6B226A5AF50075461B /* Actions */,
E4B11B5F226A4BED0075461B /* Reducers */,
E4B11B52226928F20075461B /* AppState.swift */,
E440519F227BB0AB0090CD6F /* UIState.swift */,
E4B11B65226A4F830075461B /* PlayerState.swift */,
E4B11B67226A4FA00075461B /* QueueState.swift */,
E4B11B69226A4FBC0075461B /* AlbumListState.swift */,
@ -630,6 +638,7 @@
E4B11BBF2275EE150075461B /* QueueActions.swift */,
E4FF71912276029000D4C412 /* PreferencesActions.swift */,
E4405195227879960090CD6F /* MPDActions.swift */,
E440519B227BAF2E0090CD6F /* UIActions.swift */,
);
path = Actions;
sourceTree = "<group>";
@ -909,6 +918,7 @@
E45962C62241A78500FC1A1E /* MPDCommand.swift in Sources */,
E408D3B9220DE98F0006D9BE /* NSUserInterfaceItemIdentifier.swift in Sources */,
E4EB2379220F10B8008C70C0 /* MPDPair.swift in Sources */,
E440519E227BB0720090CD6F /* UIReducer.swift in Sources */,
E4FF7190227601B400D4C412 /* PreferencesReducer.swift in Sources */,
E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */,
E4A83BF12221FAA00098FED6 /* PreferencesViewController.swift in Sources */,
@ -919,6 +929,7 @@
E41B22C621FB932700D544F6 /* MPDClient.swift in Sources */,
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */,
E419E2872249B96600216A8C /* Song.swift in Sources */,
E44051A0227BB0AB0090CD6F /* UIState.swift in Sources */,
E4FF718E2276010E00D4C412 /* PreferencesState.swift in Sources */,
E439109822640213002982E9 /* SongNotifierService.swift in Sources */,
E407861C2110CE6E006887B1 /* AppDelegate.swift in Sources */,
@ -943,6 +954,7 @@
E4FF71942276043A00D4C412 /* MPDServer.swift in Sources */,
E41E530E223EF4CF00173814 /* CoverArtService+Caching.swift in Sources */,
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
E440519C227BAF2E0090CD6F /* UIActions.swift in Sources */,
E41E5312223EF74A00173814 /* CoverArtService+Filesystem.swift in Sources */,
E41E5301223BF99300173814 /* MPDClient+Queue.swift in Sources */,
E4EB237B220F7CF1008C70C0 /* MPDAlbum.swift in Sources */,

View File

@ -24,7 +24,9 @@ class AppDelegate: NSObject,
mediaKeyTap?.start()
App.store.subscribe(self) {
$0.select { $0.playerState.databaseUpdating }
$0.select {
$0.uiState
}
}
}
@ -107,17 +109,19 @@ class AppDelegate: NSObject,
@IBAction func nextTrackMenuAction(_ sender: NSMenuItem) {
App.store.dispatch(MPDNextTrackAction())
}
@IBAction func prevTrackMenuAction(_ sender: Any) {
@IBAction func prevTrackMenuAction(_ sender: NSMenuItem) {
App.store.dispatch(MPDPrevTrackAction())
}
@IBOutlet weak var mainWindowMenuItem: NSMenuItem!
@IBOutlet weak var updateDatabaseMenuItem: NSMenuItem!
}
extension AppDelegate: StoreSubscriber {
typealias StoreSubscriberStateType = Bool
typealias StoreSubscriberStateType = UIState
func newState(state: Bool) {
updateDatabaseMenuItem.isEnabled = !state
func newState(state: UIState) {
updateDatabaseMenuItem.isEnabled = !state.databaseUpdating
mainWindowMenuItem.state = state.mainWindowOpen ? .on : .off
}
}

View File

@ -53,22 +53,6 @@ class AlbumViewController: NSViewController,
layout.setScrollPosition()
}
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?
) {
switch keyPath {
case "mpdLibraryDir":
albumCollectionView.reloadData()
case "fetchMissingArtworkFromInternet":
App.store.dispatch(ResetAlbumListCoverArtAction())
default:
break
}
}
@IBOutlet var albumScrollView: NSScrollView!
@IBOutlet var albumCollectionView: NSCollectionView!
}
@ -78,7 +62,9 @@ extension AlbumViewController: StoreSubscriber {
func newState(state: StoreSubscriberStateType) {
let oldAlbums = dataSource.albums
dataSource.albums = state.albums
albumCollectionView.animateItemChanges(
oldData: oldAlbums,
newData: dataSource.albums

View File

@ -55,13 +55,13 @@ extension MPDServerController: MPDClientDelegate {
func willStartDatabaseUpdate(mpdClient: MPDClient) {
DispatchQueue.main.async {
App.store.dispatch(StartedDatabaseUpdateAction())
App.store.dispatch(DatabaseUpdateStartedAction())
}
}
func didFinishDatabaseUpdate(mpdClient: MPDClient) {
DispatchQueue.main.async {
App.store.dispatch(FinishedDatabaseUpdateAction())
App.store.dispatch(DatabaseUpdateFinishedAction())
}
}

View File

@ -47,7 +47,7 @@ class QueueViewController: NSViewController,
func outlineView(
_ outlineView: NSOutlineView,
selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet
) -> IndexSet {
) -> IndexSet {
if proposedSelectionIndexes.contains(0) {
return IndexSet()
} else {

View File

@ -23,9 +23,13 @@ class WindowController: NSWindowController {
window?.isExcludedFromWindowsMenu = true
App.store.subscribe(self) {
$0.select { $0.playerState }
$0.select {
($0.playerState, $0.uiState)
}
}
App.store.dispatch(MainWindowDidOpenAction())
trackProgress.font = .timerFont
trackRemaining.font = .timerFont
}
@ -68,22 +72,14 @@ class WindowController: NSWindowController {
setTimeRemaining(elapsedTimeMs, totalTime * 1000)
}
func setDatabaseUpdatingIndicator(_ playerState: PlayerState) {
if playerState.databaseUpdating {
startDatabaseUpdatingIndicator()
func setDatabaseUpdatingIndicator(_ uiState: UIState) {
if uiState.databaseUpdating {
databaseUpdatingIndicator.startAnimation(self)
} else {
stopDatabaseUpdatingIndicator()
databaseUpdatingIndicator.stopAnimation(self)
}
}
func startDatabaseUpdatingIndicator() {
databaseUpdatingIndicator.startAnimation(self)
}
func stopDatabaseUpdatingIndicator() {
databaseUpdatingIndicator.stopAnimation(self)
}
func setTimeElapsed(_ elapsedTimeMs: UInt?) {
guard let elapsedTimeMs = elapsedTimeMs else { return }
@ -149,16 +145,20 @@ class WindowController: NSWindowController {
@IBOutlet var databaseUpdatingIndicator: NSProgressIndicator!
}
extension WindowController: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
App.store.dispatch(MainWindowDidCloseAction())
}
}
extension WindowController: StoreSubscriber {
typealias StoreSubscriberStateType = PlayerState
func newState(state: StoreSubscriberStateType) {
self.state = state.state
typealias StoreSubscriberStateType = (playerState: PlayerState, uiState: UIState)
func newState(state: (playerState: PlayerState, uiState: UIState)) {
DispatchQueue.main.async {
self.setTransportControlState(state)
self.setTrackProgressControls(state)
self.setDatabaseUpdatingIndicator(state)
self.setTransportControlState(state.playerState)
self.setTrackProgressControls(state.playerState)
self.setDatabaseUpdatingIndicator(state.uiState)
}
}
}

View File

@ -26,7 +26,7 @@
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW">
<connections>
<action selector="preferencesItemSelected:" target="Voe-Tx-rLC" id="bxe-zW-cho"/>
<segue destination="xYu-7w-E5x" kind="show" id="OTW-56-v9E"/>
<segue destination="xYu-7w-E5x" kind="show" identifier="Preferences" id="OTW-56-v9E"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
@ -90,8 +90,17 @@
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="ahn-71-IzA">
<connections>
<action selector="performClose:" target="Ady-hI-5gd" id="ADY-rv-28Y"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="QhP-iz-rRa"/>
<menuItem title="Persephone" state="on" keyEquivalent="0" id="1Sq-L7-znT"/>
<menuItem title="Persephone" keyEquivalent="0" id="1Sq-L7-znT">
<connections>
<segue destination="B8D-0N-5wS" kind="show" identifier="Main Window" id="D1q-xT-4O8"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
@ -122,6 +131,7 @@
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Persephone" customModuleProvider="target">
<connections>
<outlet property="mainWindowMenuItem" destination="1Sq-L7-znT" id="dC6-yY-6Ss"/>
<outlet property="updateDatabaseMenuItem" destination="EJg-93-1F6" id="gMf-SQ-lyI"/>
</connections>
</customObject>
@ -133,7 +143,7 @@
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" customClass="WindowController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
<windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" customClass="WindowController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Persephone" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA" customClass="MainWindow" customModule="Persephone" customModuleProvider="target">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
@ -267,8 +277,8 @@
<!--Window Controller-->
<scene sceneID="Rpk-bo-5kf">
<objects>
<windowController id="xYu-7w-E5x" customClass="PreferencesWindowController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="3FN-my-6kU">
<windowController showSeguePresentationStyle="single" id="xYu-7w-E5x" customClass="PreferencesWindowController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" titleVisibility="hidden" id="3FN-my-6kU">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<rect key="contentRect" x="245" y="301" width="416" height="100"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>

View File

@ -24,7 +24,3 @@ struct UpdateElapsedTimeAction: Action {
struct UpdateStatusAction: Action {
var status: MPDClient.MPDStatus
}
struct StartedDatabaseUpdateAction: Action {}
struct FinishedDatabaseUpdateAction: Action {}

View File

@ -0,0 +1,17 @@
//
// UIActions.swift
// Persephone
//
// Created by Daniel Barber on 2019/5/02.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
struct MainWindowDidOpenAction: Action {}
struct MainWindowDidCloseAction: Action {}
struct DatabaseUpdateStartedAction: Action {}
struct DatabaseUpdateFinishedAction: Action {}

View File

@ -14,4 +14,5 @@ struct AppState: StateType {
var albumListState = AlbumListState()
var preferencesState = PreferencesState()
var mpdState = MPDState()
var uiState = UIState()
}

View File

@ -18,15 +18,12 @@ struct PlayerState: StateType {
var totalTime: UInt?
var elapsedTimeMs: UInt?
var databaseUpdating: Bool = false
}
extension PlayerState: Equatable {
static func == (lhs: PlayerState, rhs: PlayerState) -> Bool {
return (lhs.state == rhs.state) &&
(lhs.totalTime == rhs.totalTime) &&
(lhs.elapsedTimeMs == rhs.elapsedTimeMs) &&
(lhs.databaseUpdating == rhs.databaseUpdating)
(lhs.elapsedTimeMs == rhs.elapsedTimeMs)
}
}

View File

@ -14,6 +14,7 @@ func appReducer(action: Action, state: AppState?) -> AppState {
queueState: queueReducer(action: action, state: state?.queueState),
albumListState: albumListReducer(action: action, state: state?.albumListState),
preferencesState: preferencesReducer(action: action, state: state?.preferencesState),
mpdState: mpdReducer(action: action, state: state?.mpdState)
mpdState: mpdReducer(action: action, state: state?.mpdState),
uiState: uiReducer(action: action, state: state?.uiState)
)
}

View File

@ -60,12 +60,6 @@ func playerReducer(action: Action, state: PlayerState?) -> PlayerState {
case let action as UpdateElapsedTimeAction:
state.elapsedTimeMs = action.elapsedTimeMs
case is StartedDatabaseUpdateAction:
state.databaseUpdating = true
case is FinishedDatabaseUpdateAction:
state.databaseUpdating = false
default:
break
}

View File

@ -0,0 +1,32 @@
//
// UIReducer.swift
// Persephone
//
// Created by Daniel Barber on 2019/5/02.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
func uiReducer(action: Action, state: UIState?) -> UIState {
var state = state ?? UIState()
switch action {
case is MainWindowDidOpenAction:
state.mainWindowOpen = true
case is MainWindowDidCloseAction:
state.mainWindowOpen = false
case is DatabaseUpdateStartedAction:
state.databaseUpdating = true
case is DatabaseUpdateFinishedAction:
state.databaseUpdating = false
default:
break
}
return state
}

View File

@ -0,0 +1,14 @@
//
// UIState.swift
// Persephone
//
// Created by Daniel Barber on 2019/5/02.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import ReSwift
struct UIState: StateType {
var mainWindowOpen: Bool = false
var databaseUpdating: Bool = false
}