From fc447121d665fef7e1c212ee818884dedfaf1014 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 5 Mar 2020 17:42:17 -0700 Subject: [PATCH] Save window state to user defaults. Issue #1852 --- Mac/AppDefaults.swift | 10 ++++++++++ Mac/AppDelegate.swift | 21 ++++++++++++++++----- Mac/MainWindow/MainWindowController.swift | 16 ++++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Mac/AppDefaults.swift b/Mac/AppDefaults.swift index c429f26fc..a74afc140 100644 --- a/Mac/AppDefaults.swift +++ b/Mac/AppDefaults.swift @@ -18,6 +18,7 @@ struct AppDefaults { struct Key { static let firstRunDate = "firstRunDate" + static let windowState = "windowState" static let lastImageCacheFlushDate = "lastImageCacheFlushDate" static let sidebarFontSize = "sidebarFontSize" static let timelineFontSize = "timelineFontSize" @@ -55,6 +56,15 @@ struct AppDefaults { return true }() + static var windowState: [AnyHashable : Any]? { + get { + UserDefaults.standard.object(forKey: Key.windowState) as? [AnyHashable : Any] + } + set { + UserDefaults.standard.set(newValue, forKey: Key.windowState) + } + } + static var lastImageCacheFlushDate: Date? { get { return date(for: Key.lastImageCacheFlushDate) diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index 7bfef0737..b771a5530 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -207,8 +207,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, updateSortMenuItems() updateGroupByFeedMenuItem() - createAndShowMainWindowIfNecessary() - + + if mainWindowController == nil { + let mainWindowController = createAndShowMainWindow() + mainWindowController.restoreStateFromUserDefaults() + } + if isFirstRun { mainWindowController?.window?.center() } @@ -354,6 +358,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, func createMainWindowController() -> MainWindowController { let controller = windowControllerWithName("MainWindow") as! MainWindowController + if !(mainWindowController?.isOpen ?? false) { + mainWindowControllers.removeAll() + } mainWindowControllers.append(controller) return controller } @@ -364,7 +371,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } @discardableResult - func createAndShowMainWindow() -> NSWindow? { + func createAndShowMainWindow() -> MainWindowController { let controller = createMainWindowController() controller.showWindow(self) @@ -373,16 +380,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, window.identifier = NSUserInterfaceItemIdentifier(rawValue: WindowRestorationIdentifiers.mainWindow) } - return controller.window + return controller } func createAndShowMainWindowIfNecessary() { if mainWindowController == nil { createAndShowMainWindow() + } else { + mainWindowController?.showWindow(self) } } func removeMainWindow(_ windowController: MainWindowController) { + guard mainWindowControllers.count > 1 else { return } if let index = mainWindowControllers.firstIndex(of: windowController) { mainWindowControllers.remove(at: index) } @@ -684,6 +694,7 @@ private extension AppDelegate { } func saveState() { + mainWindowController?.saveStateToUserDefaults() inspectorWindowController?.saveState() } @@ -727,7 +738,7 @@ extension AppDelegate: NSWindowRestoration { @objc static func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: @escaping (NSWindow?, Error?) -> Void) { var mainWindow: NSWindow? = nil if identifier.rawValue == WindowRestorationIdentifiers.mainWindow { - mainWindow = appDelegate.createAndShowMainWindow() + mainWindow = appDelegate.createAndShowMainWindow().window } completionHandler(mainWindow, nil) } diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index c5159dc8b..06ddbf865 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -24,6 +24,7 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { private var articleExtractor: ArticleExtractor? = nil private var sharingServicePickerDelegate: NSSharingServicePickerDelegate? + private let windowAutosaveName = NSWindow.FrameAutosaveName("MainWindow") private static let mainWindowWidthsStateKey = "mainWindowWidthsStateKey" private var currentFeedOrFolder: AnyObject? { @@ -63,7 +64,7 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { if !AppDefaults.showTitleOnMainWindow { window?.titleVisibility = .hidden } - + if let window = window { let point = NSPoint(x: 128, y: 64) let size = NSSize(width: 1000, height: 700) @@ -113,6 +114,18 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { currentTimelineViewController?.goToDeepLink(for: articlePathUserInfo) } + func saveStateToUserDefaults() { + AppDefaults.windowState = savableState() + window?.saveFrame(usingName: windowAutosaveName) + } + + func restoreStateFromUserDefaults() { + if let state = AppDefaults.windowState { + restoreState(from: state) + window?.setFrameUsingName(windowAutosaveName, force: true) + } + } + // MARK: - Notifications @objc func refreshProgressDidChange(_ note: Notification) { @@ -435,7 +448,6 @@ extension MainWindowController: NSWindowDelegate { } func windowWillClose(_ notification: Notification) { - // TODO: now that we are deallocating main window controllers, the media playback stop can probably be removed detailViewController?.stopMediaPlayback() appDelegate.removeMainWindow(self) }