Revert the state restoration changes, because it needs more study. We’ll revisit this when we add multiple window support, some time after 5.0 ships.
This commit is contained in:
parent
1950b0ab47
commit
752b697505
|
@ -53,6 +53,7 @@ struct AppDefaults {
|
||||||
static let timelineSortDirection = "timelineSortDirection"
|
static let timelineSortDirection = "timelineSortDirection"
|
||||||
static let detailFontSize = "detailFontSize"
|
static let detailFontSize = "detailFontSize"
|
||||||
static let openInBrowserInBackground = "openInBrowserInBackground"
|
static let openInBrowserInBackground = "openInBrowserInBackground"
|
||||||
|
static let mainWindowWidths = "mainWindowWidths"
|
||||||
static let refreshInterval = "refreshInterval"
|
static let refreshInterval = "refreshInterval"
|
||||||
|
|
||||||
// Hidden prefs
|
// Hidden prefs
|
||||||
|
@ -119,6 +120,15 @@ struct AppDefaults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var mainWindowWidths: [Int]? {
|
||||||
|
get {
|
||||||
|
return UserDefaults.standard.object(forKey: Key.mainWindowWidths) as? [Int]
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
UserDefaults.standard.set(newValue, forKey: Key.mainWindowWidths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static var refreshInterval: RefreshInterval {
|
static var refreshInterval: RefreshInterval {
|
||||||
get {
|
get {
|
||||||
let rawValue = UserDefaults.standard.integer(forKey: Key.refreshInterval)
|
let rawValue = UserDefaults.standard.integer(forKey: Key.refreshInterval)
|
||||||
|
@ -144,7 +154,9 @@ struct AppDefaults {
|
||||||
// to NetNewsWire preserving this state, we'll force the preference on. If this becomes
|
// to NetNewsWire preserving this state, we'll force the preference on. If this becomes
|
||||||
// an issue, this could be changed to proactively look for whether the default has been
|
// an issue, this could be changed to proactively look for whether the default has been
|
||||||
// set _by the user_ to false, and respect that default if it is so-set.
|
// set _by the user_ to false, and respect that default if it is so-set.
|
||||||
UserDefaults.standard.set(true, forKey: "NSQuitAlwaysKeepsWindows")
|
// UserDefaults.standard.set(true, forKey: "NSQuitAlwaysKeepsWindows")
|
||||||
|
|
||||||
|
// TODO: revisit the above when coming back to state restoration issues.
|
||||||
}
|
}
|
||||||
|
|
||||||
static func actualFontSize(for fontSize: FontSize) -> CGFloat {
|
static func actualFontSize(for fontSize: FontSize) -> CGFloat {
|
||||||
|
|
|
@ -584,6 +584,7 @@ private extension AppDelegate {
|
||||||
func saveState() {
|
func saveState() {
|
||||||
|
|
||||||
inspectorWindowController?.saveState()
|
inspectorWindowController?.saveState()
|
||||||
|
mainWindowController?.saveState()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSortMenuItems() {
|
func updateSortMenuItems() {
|
||||||
|
|
|
@ -15,10 +15,11 @@ enum TimelineSourceMode {
|
||||||
case regular, search
|
case regular, search
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainWindowController : NSWindowController, NSUserInterfaceValidations, NSWindowDelegate {
|
class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
||||||
|
|
||||||
private var sharingServicePickerDelegate: NSSharingServicePickerDelegate?
|
private var sharingServicePickerDelegate: NSSharingServicePickerDelegate?
|
||||||
|
|
||||||
|
private let windowAutosaveName = NSWindow.FrameAutosaveName("MainWindow")
|
||||||
static var didPositionWindowOnFirstRun = false
|
static var didPositionWindowOnFirstRun = false
|
||||||
|
|
||||||
private var currentFeedOrFolder: AnyObject? {
|
private var currentFeedOrFolder: AnyObject? {
|
||||||
|
@ -60,6 +61,7 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations, NSW
|
||||||
window?.titleVisibility = .hidden
|
window?.titleVisibility = .hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window?.setFrameUsingName(windowAutosaveName, force: true)
|
||||||
if AppDefaults.isFirstRun && !MainWindowController.didPositionWindowOnFirstRun {
|
if AppDefaults.isFirstRun && !MainWindowController.didPositionWindowOnFirstRun {
|
||||||
|
|
||||||
if let window = window {
|
if let window = window {
|
||||||
|
@ -72,6 +74,9 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations, NSW
|
||||||
}
|
}
|
||||||
|
|
||||||
detailSplitViewItem?.minimumThickness = CGFloat(MainWindowController.detailViewMinimumThickness)
|
detailSplitViewItem?.minimumThickness = CGFloat(MainWindowController.detailViewMinimumThickness)
|
||||||
|
restoreSplitViewState()
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillTerminate(_:)), name: NSApplication.willTerminateNotification, object: nil)
|
||||||
|
|
||||||
sidebarViewController = splitViewController?.splitViewItems[0].viewController as? SidebarViewController
|
sidebarViewController = splitViewController?.splitViewItems[0].viewController as? SidebarViewController
|
||||||
sidebarViewController!.delegate = self
|
sidebarViewController!.delegate = self
|
||||||
|
@ -95,6 +100,11 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations, NSW
|
||||||
|
|
||||||
// MARK: - API
|
// MARK: - API
|
||||||
|
|
||||||
|
func saveState() {
|
||||||
|
|
||||||
|
saveSplitViewState()
|
||||||
|
}
|
||||||
|
|
||||||
func selectedObjectsInSidebar() -> [AnyObject]? {
|
func selectedObjectsInSidebar() -> [AnyObject]? {
|
||||||
|
|
||||||
return sidebarViewController?.selectedObjects
|
return sidebarViewController?.selectedObjects
|
||||||
|
@ -102,18 +112,23 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations, NSW
|
||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
|
|
||||||
func window(_ window: NSWindow, willEncodeRestorableState state: NSCoder) {
|
// func window(_ window: NSWindow, willEncodeRestorableState state: NSCoder) {
|
||||||
|
//
|
||||||
|
// saveSplitViewState(to: state)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func window(_ window: NSWindow, didDecodeRestorableState state: NSCoder) {
|
||||||
|
//
|
||||||
|
// restoreSplitViewState(from: state)
|
||||||
|
//
|
||||||
|
// // Make sure the timeline view is first responder if possible, to start out viewing
|
||||||
|
// // whatever preserved selection might have been restored
|
||||||
|
// makeTimelineViewFirstResponder()
|
||||||
|
// }
|
||||||
|
|
||||||
saveSplitViewState(to: state)
|
@objc func applicationWillTerminate(_ note: Notification) {
|
||||||
}
|
saveState()
|
||||||
|
window?.saveFrame(usingName: windowAutosaveName)
|
||||||
func window(_ window: NSWindow, didDecodeRestorableState state: NSCoder) {
|
|
||||||
|
|
||||||
restoreSplitViewState(from: state)
|
|
||||||
|
|
||||||
// Make sure the timeline view is first responder if possible, to start out viewing
|
|
||||||
// whatever preserved selection might have been restored
|
|
||||||
makeTimelineViewFirstResponder()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func refreshProgressDidChange(_ note: Notification) {
|
@objc func refreshProgressDidChange(_ note: Notification) {
|
||||||
|
@ -523,8 +538,6 @@ extension MainWindowController: NSToolbarDelegate {
|
||||||
|
|
||||||
private extension MainWindowController {
|
private extension MainWindowController {
|
||||||
|
|
||||||
static let mainWindowWidthsStateKey = "mainWindowWidths"
|
|
||||||
|
|
||||||
var splitViewController: NSSplitViewController? {
|
var splitViewController: NSSplitViewController? {
|
||||||
guard let viewController = contentViewController else {
|
guard let viewController = contentViewController else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -703,37 +716,24 @@ private extension MainWindowController {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveSplitViewState(to coder: NSCoder) {
|
func saveSplitViewState() {
|
||||||
|
|
||||||
// TODO: Update this for multiple windows.
|
// TODO: Update this for multiple windows.
|
||||||
|
// Also: use standard state restoration mechanism.
|
||||||
guard let splitView = splitViewController?.splitView else {
|
guard let splitView = splitViewController?.splitView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) }
|
let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) }
|
||||||
coder.encode(widths, forKey: MainWindowController.mainWindowWidthsStateKey)
|
if AppDefaults.mainWindowWidths != widths {
|
||||||
|
AppDefaults.mainWindowWidths = widths
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func arrayOfIntFromCoder(_ coder: NSCoder, withKey: String) -> [Int]? {
|
func restoreSplitViewState() {
|
||||||
let decodedFloats: [Int]?
|
|
||||||
do {
|
|
||||||
decodedFloats = try coder.decodeTopLevelObject(forKey: MainWindowController.mainWindowWidthsStateKey) as? [Int]? ?? nil
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
decodedFloats = nil
|
|
||||||
}
|
|
||||||
return decodedFloats
|
|
||||||
}
|
|
||||||
|
|
||||||
func restoreSplitViewState(from coder: NSCoder) {
|
|
||||||
|
|
||||||
// TODO: Update this for multiple windows.
|
// TODO: Update this for multiple windows.
|
||||||
guard let splitView = splitViewController?.splitView, let widths = arrayOfIntFromCoder(coder, withKey: MainWindowController.mainWindowWidthsStateKey), widths.count == 3, let window = window else {
|
// Also: use standard state restoration mechanism.
|
||||||
|
guard let splitView = splitViewController?.splitView, let widths = AppDefaults.mainWindowWidths, widths.count == 3, let window = window else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let windowWidth = Int(floor(window.frame.width))
|
let windowWidth = Int(floor(window.frame.width))
|
||||||
let dividerThickness: Int = Int(splitView.dividerThickness)
|
let dividerThickness: Int = Int(splitView.dividerThickness)
|
||||||
let sidebarWidth: Int = widths[0]
|
let sidebarWidth: Int = widths[0]
|
||||||
|
@ -748,5 +748,49 @@ private extension MainWindowController {
|
||||||
splitView.setPosition(CGFloat(sidebarWidth + dividerThickness + timelineWidth), ofDividerAt: 1)
|
splitView.setPosition(CGFloat(sidebarWidth + dividerThickness + timelineWidth), ofDividerAt: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func saveSplitViewState(to coder: NSCoder) {
|
||||||
|
//
|
||||||
|
// // TODO: Update this for multiple windows.
|
||||||
|
//
|
||||||
|
// guard let splitView = splitViewController?.splitView else {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) }
|
||||||
|
// coder.encode(widths, forKey: MainWindowController.mainWindowWidthsStateKey)
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func arrayOfIntFromCoder(_ coder: NSCoder, withKey: String) -> [Int]? {
|
||||||
|
// let decodedFloats: [Int]?
|
||||||
|
// do {
|
||||||
|
// decodedFloats = try coder.decodeTopLevelObject(forKey: MainWindowController.mainWindowWidthsStateKey) as? [Int]? ?? nil
|
||||||
|
// }
|
||||||
|
// catch {
|
||||||
|
// decodedFloats = nil
|
||||||
|
// }
|
||||||
|
// return decodedFloats
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func restoreSplitViewState(from coder: NSCoder) {
|
||||||
|
//
|
||||||
|
// // TODO: Update this for multiple windows.
|
||||||
|
// guard let splitView = splitViewController?.splitView, let widths = arrayOfIntFromCoder(coder, withKey: MainWindowController.mainWindowWidthsStateKey), widths.count == 3, let window = window else {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// let windowWidth = Int(floor(window.frame.width))
|
||||||
|
// let dividerThickness: Int = Int(splitView.dividerThickness)
|
||||||
|
// let sidebarWidth: Int = widths[0]
|
||||||
|
// let timelineWidth: Int = widths[1]
|
||||||
|
//
|
||||||
|
// // Make sure the detail view has its mimimum thickness, at least.
|
||||||
|
// if windowWidth < sidebarWidth + dividerThickness + timelineWidth + dividerThickness + MainWindowController.detailViewMinimumThickness {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// splitView.setPosition(CGFloat(sidebarWidth), ofDividerAt: 0)
|
||||||
|
// splitView.setPosition(CGFloat(sidebarWidth + dividerThickness + timelineWidth), ofDividerAt: 1)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,23 +78,23 @@ protocol SidebarDelegate: class {
|
||||||
|
|
||||||
// MARK: State Restoration
|
// MARK: State Restoration
|
||||||
|
|
||||||
private static let stateRestorationSelectedRowIndexes = "selectedRowIndexes"
|
// private static let stateRestorationSelectedRowIndexes = "selectedRowIndexes"
|
||||||
|
//
|
||||||
override func encodeRestorableState(with coder: NSCoder) {
|
// override func encodeRestorableState(with coder: NSCoder) {
|
||||||
|
//
|
||||||
super.encodeRestorableState(with: coder)
|
// super.encodeRestorableState(with: coder)
|
||||||
|
//
|
||||||
coder.encode(outlineView.selectedRowIndexes, forKey: SidebarViewController.stateRestorationSelectedRowIndexes)
|
// coder.encode(outlineView.selectedRowIndexes, forKey: SidebarViewController.stateRestorationSelectedRowIndexes)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override func restoreState(with coder: NSCoder) {
|
// override func restoreState(with coder: NSCoder) {
|
||||||
|
//
|
||||||
super.restoreState(with: coder)
|
// super.restoreState(with: coder)
|
||||||
|
//
|
||||||
if let restoredRowIndexes = coder.decodeObject(of: [NSIndexSet.self], forKey: SidebarViewController.stateRestorationSelectedRowIndexes) as? IndexSet {
|
// if let restoredRowIndexes = coder.decodeObject(of: [NSIndexSet.self], forKey: SidebarViewController.stateRestorationSelectedRowIndexes) as? IndexSet {
|
||||||
outlineView.selectRowIndexes(restoredRowIndexes, byExtendingSelection: false)
|
// outlineView.selectRowIndexes(restoredRowIndexes, byExtendingSelection: false)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ protocol SidebarDelegate: class {
|
||||||
|
|
||||||
func outlineViewSelectionDidChange(_ notification: Notification) {
|
func outlineViewSelectionDidChange(_ notification: Notification) {
|
||||||
selectionDidChange(selectedObjects.isEmpty ? nil : selectedObjects)
|
selectionDidChange(selectedObjects.isEmpty ? nil : selectedObjects)
|
||||||
self.invalidateRestorableState()
|
// self.invalidateRestorableState()
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - Node Manipulation
|
//MARK: - Node Manipulation
|
||||||
|
|
|
@ -156,23 +156,23 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner {
|
||||||
|
|
||||||
// MARK: State Restoration
|
// MARK: State Restoration
|
||||||
|
|
||||||
private static let stateRestorationSelectedArticles = "selectedArticles"
|
// private static let stateRestorationSelectedArticles = "selectedArticles"
|
||||||
|
//
|
||||||
override func encodeRestorableState(with coder: NSCoder) {
|
// override func encodeRestorableState(with coder: NSCoder) {
|
||||||
|
//
|
||||||
super.encodeRestorableState(with: coder)
|
// super.encodeRestorableState(with: coder)
|
||||||
|
//
|
||||||
coder.encode(self.selectedArticleIDs(), forKey: TimelineViewController.stateRestorationSelectedArticles)
|
// coder.encode(self.selectedArticleIDs(), forKey: TimelineViewController.stateRestorationSelectedArticles)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override func restoreState(with coder: NSCoder) {
|
// override func restoreState(with coder: NSCoder) {
|
||||||
|
//
|
||||||
super.restoreState(with: coder)
|
// super.restoreState(with: coder)
|
||||||
|
//
|
||||||
if let restoredArticleIDs = (try? coder.decodeTopLevelObject(forKey: TimelineViewController.stateRestorationSelectedArticles)) as? [String] {
|
// if let restoredArticleIDs = (try? coder.decodeTopLevelObject(forKey: TimelineViewController.stateRestorationSelectedArticles)) as? [String] {
|
||||||
self.restoreSelection(restoredArticleIDs)
|
// self.restoreSelection(restoredArticleIDs)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// MARK: Appearance Change
|
// MARK: Appearance Change
|
||||||
|
|
||||||
|
@ -647,7 +647,7 @@ extension TimelineViewController: NSTableViewDelegate {
|
||||||
|
|
||||||
selectionDidChange(selectedArticles)
|
selectionDidChange(selectedArticles)
|
||||||
|
|
||||||
self.invalidateRestorableState()
|
// self.invalidateRestorableState()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func selectionDidChange(_ selectedArticles: ArticleArray?) {
|
private func selectionDidChange(_ selectedArticles: ArticleArray?) {
|
||||||
|
|
Loading…
Reference in New Issue