Refactor so that state could be restored from alternate sources (such as UserDefaults).

This commit is contained in:
Maurice Parker 2020-03-05 16:42:54 -07:00
parent 59e4cf8695
commit 7bc5a7946f
4 changed files with 43 additions and 28 deletions

View File

@ -426,15 +426,12 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
extension MainWindowController: NSWindowDelegate {
func window(_ window: NSWindow, willEncodeRestorableState coder: NSCoder) {
saveSplitViewState(to: coder)
sidebarViewController?.saveState(to: coder)
timelineContainerViewController?.saveState(to: coder)
coder.encode(savableState(), forKey: UserInfoKey.windowState)
}
func window(_ window: NSWindow, didDecodeRestorableState coder: NSCoder) {
restoreSplitViewState(from: coder)
sidebarViewController?.restoreState(from: coder)
timelineContainerViewController?.restoreState(from: coder)
guard let state = try? coder.decodeTopLevelObject(forKey: UserInfoKey.windowState) as? [AnyHashable : Any] else { return }
restoreState(from: state)
}
func windowWillClose(_ notification: Notification) {
@ -704,6 +701,22 @@ private extension MainWindowController {
return oneSelectedArticle?.preferredLink
}
// MARK: - State Restoration
func savableState() -> [AnyHashable : Any] {
var state = [AnyHashable : Any]()
saveSplitViewState(to: &state)
sidebarViewController?.saveState(to: &state)
timelineContainerViewController?.saveState(to: &state)
return state
}
func restoreState(from state: [AnyHashable : Any]) {
restoreSplitViewState(from: state)
sidebarViewController?.restoreState(from: state)
timelineContainerViewController?.restoreState(from: state)
}
// MARK: - Command Validation
func canGoToNextUnread() -> Bool {
@ -912,18 +925,18 @@ private extension MainWindowController {
}
}
func saveSplitViewState(to coder: NSCoder) {
func saveSplitViewState(to state: inout [AnyHashable : Any]) {
guard let splitView = splitViewController?.splitView else {
return
}
let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) }
coder.encode(widths, forKey: MainWindowController.mainWindowWidthsStateKey)
state[MainWindowController.mainWindowWidthsStateKey] = widths
}
func restoreSplitViewState(from coder: NSCoder) {
func restoreSplitViewState(from state: [AnyHashable : Any]) {
guard let splitView = splitViewController?.splitView,
let widths = try? coder.decodeTopLevelObject(forKey: MainWindowController.mainWindowWidthsStateKey) as? [Int],
let widths = state[MainWindowController.mainWindowWidthsStateKey] as? [Int],
widths.count == 3,
let window = window else {
return

View File

@ -90,20 +90,20 @@ protocol SidebarDelegate: class {
// MARK: State Restoration
func saveState(to coder: NSCoder) {
coder.encode(isReadFiltered, forKey: UserInfoKey.readFeedsFilterState)
coder.encode(expandedTable.map( { $0.userInfo }), forKey: UserInfoKey.containerExpandedWindowState)
coder.encode(selectedFeeds.compactMap({ $0.feedID?.userInfo }), forKey: UserInfoKey.selectedFeedsState)
func saveState(to state: inout [AnyHashable : Any]) {
state[UserInfoKey.readFeedsFilterState] = isReadFiltered
state[UserInfoKey.containerExpandedWindowState] = expandedTable.map { $0.userInfo }
state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.feedID?.userInfo }
}
func restoreState(from coder: NSCoder) {
func restoreState(from state: [AnyHashable : Any]) {
if let containerExpandedWindowState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.containerExpandedWindowState) as? [[AnyHashable: AnyHashable]] {
if let containerExpandedWindowState = state[UserInfoKey.containerExpandedWindowState] as? [[AnyHashable: AnyHashable]] {
let containerIdentifers = containerExpandedWindowState.compactMap( { ContainerIdentifier(userInfo: $0) })
expandedTable = Set(containerIdentifers)
}
guard let selectedFeedsState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.selectedFeedsState) as? [[AnyHashable: AnyHashable]] else {
guard let selectedFeedsState = state[UserInfoKey.selectedFeedsState] as? [[AnyHashable: AnyHashable]] else {
return
}
@ -126,7 +126,9 @@ protocol SidebarDelegate: class {
outlineView.selectRowIndexes(selectIndexes, byExtendingSelection: false)
focus()
isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState)
if let readFeedsFilterState = state[UserInfoKey.readFeedsFilterState] as? Bool {
isReadFiltered = readFeedsFilterState
}
}
// MARK: - Notifications

View File

@ -95,12 +95,12 @@ final class TimelineContainerViewController: NSViewController {
// MARK: State Restoration
func saveState(to coder: NSCoder) {
regularTimelineViewController.saveState(to: coder)
func saveState(to state: inout [AnyHashable : Any]) {
regularTimelineViewController.saveState(to: &state)
}
func restoreState(from coder: NSCoder) {
regularTimelineViewController.restoreState(from: coder)
func restoreState(from state: [AnyHashable : Any]) {
regularTimelineViewController.restoreState(from: state)
}
}

View File

@ -247,20 +247,20 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
// MARK: State Restoration
func saveState(to coder: NSCoder) {
func saveState(to state: inout [AnyHashable : Any]) {
var readArticlesFilterState = [[AnyHashable: AnyHashable]: Bool]()
for key in readFilterEnabledTable.keys {
readArticlesFilterState[key.userInfo] = readFilterEnabledTable[key]
}
coder.encode(readArticlesFilterState, forKey: UserInfoKey.readArticlesFilterState)
state[UserInfoKey.readArticlesFilterState] = readArticlesFilterState
if selectedArticles.count == 1 {
coder.encode(selectedArticles.first!.pathUserInfo, forKey: UserInfoKey.articlePath)
state[UserInfoKey.articlePath] = selectedArticles.first!.pathUserInfo
}
}
func restoreState(from coder: NSCoder) {
if let readArticlesFilterState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.readArticlesFilterState) as? [[AnyHashable: AnyHashable]: Bool] {
func restoreState(from state: [AnyHashable : Any]) {
if let readArticlesFilterState = state[UserInfoKey.readArticlesFilterState] as? [[AnyHashable: AnyHashable]: Bool] {
for key in readArticlesFilterState.keys {
if let feedIdentifier = FeedIdentifier(userInfo: key) {
readFilterEnabledTable[feedIdentifier] = readArticlesFilterState[key]
@ -268,7 +268,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
}
}
guard let articlePathUserInfo = try? coder.decodeTopLevelObject(forKey: UserInfoKey.articlePath) as? [AnyHashable : Any],
guard let articlePathUserInfo = state[UserInfoKey.articlePath] as? [AnyHashable : Any],
let accountID = articlePathUserInfo[ArticlePathKey.accountID] as? String,
let account = AccountManager.shared.existingAccount(with: accountID),
let articleID = articlePathUserInfo[ArticlePathKey.articleID] as? String else {