mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-02-02 20:16:54 +01:00
Initial support for multiple windows and state preservation.
This commit is contained in:
parent
5755dd0844
commit
eaa99db5c7
@ -29,6 +29,10 @@ var appDelegate: AppDelegate!
|
|||||||
class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, UNUserNotificationCenterDelegate, UnreadCountProvider, SPUStandardUserDriverDelegate, SPUUpdaterDelegate
|
class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, UNUserNotificationCenterDelegate, UnreadCountProvider, SPUStandardUserDriverDelegate, SPUUpdaterDelegate
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private struct WindowRestorationIdentifiers {
|
||||||
|
static let mainWindow = "mainWindow"
|
||||||
|
}
|
||||||
|
|
||||||
var userNotificationManager: UserNotificationManager!
|
var userNotificationManager: UserNotificationManager!
|
||||||
var faviconDownloader: FaviconDownloader!
|
var faviconDownloader: FaviconDownloader!
|
||||||
var imageDownloader: ImageDownloader!
|
var imageDownloader: ImageDownloader!
|
||||||
@ -65,8 +69,22 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var mainWindowController: MainWindowController? {
|
||||||
|
var bestController: MainWindowController?
|
||||||
|
for candidateController in mainWindowControllers {
|
||||||
|
if let bestWindow = bestController?.window, let candidateWindow = candidateController.window {
|
||||||
|
if bestWindow.orderedIndex > candidateWindow.orderedIndex {
|
||||||
|
bestController = candidateController
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bestController = candidateController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestController
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mainWindowControllers = [MainWindowController]()
|
||||||
private var preferencesWindowController: NSWindowController?
|
private var preferencesWindowController: NSWindowController?
|
||||||
private var mainWindowController: MainWindowController?
|
|
||||||
private var addFeedController: AddFeedController?
|
private var addFeedController: AddFeedController?
|
||||||
private var addFolderWindowController: AddFolderWindowController?
|
private var addFolderWindowController: AddFolderWindowController?
|
||||||
private var importOPMLController: ImportOPMLWindowController?
|
private var importOPMLController: ImportOPMLWindowController?
|
||||||
@ -126,6 +144,32 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
|
|
||||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||||
installAppleEventHandlers()
|
installAppleEventHandlers()
|
||||||
|
|
||||||
|
CacheCleaner.purgeIfNecessary()
|
||||||
|
|
||||||
|
// Try to establish a cache in the Caches folder, but if it fails for some reason fall back to a temporary dir
|
||||||
|
let cacheFolder: String
|
||||||
|
if let userCacheFolder = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path {
|
||||||
|
cacheFolder = userCacheFolder
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let bundleIdentifier = (Bundle.main.infoDictionary!["CFBundleIdentifier"]! as! String)
|
||||||
|
cacheFolder = (NSTemporaryDirectory() as NSString).appendingPathComponent(bundleIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
let faviconsFolder = (cacheFolder as NSString).appendingPathComponent("Favicons")
|
||||||
|
let faviconsFolderURL = URL(fileURLWithPath: faviconsFolder)
|
||||||
|
try! FileManager.default.createDirectory(at: faviconsFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
faviconDownloader = FaviconDownloader(folder: faviconsFolder)
|
||||||
|
|
||||||
|
let imagesFolder = (cacheFolder as NSString).appendingPathComponent("Images")
|
||||||
|
let imagesFolderURL = URL(fileURLWithPath: imagesFolder)
|
||||||
|
try! FileManager.default.createDirectory(at: imagesFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
imageDownloader = ImageDownloader(folder: imagesFolder)
|
||||||
|
|
||||||
|
authorAvatarDownloader = AuthorAvatarDownloader(imageDownloader: imageDownloader)
|
||||||
|
webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: cacheFolder)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ note: Notification) {
|
func applicationDidFinishLaunching(_ note: Notification) {
|
||||||
@ -162,34 +206,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CacheCleaner.purgeIfNecessary()
|
|
||||||
|
|
||||||
// Try to establish a cache in the Caches folder, but if it fails for some reason fall back to a temporary dir
|
|
||||||
let cacheFolder: String
|
|
||||||
if let userCacheFolder = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path {
|
|
||||||
cacheFolder = userCacheFolder
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let bundleIdentifier = (Bundle.main.infoDictionary!["CFBundleIdentifier"]! as! String)
|
|
||||||
cacheFolder = (NSTemporaryDirectory() as NSString).appendingPathComponent(bundleIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
let faviconsFolder = (cacheFolder as NSString).appendingPathComponent("Favicons")
|
|
||||||
let faviconsFolderURL = URL(fileURLWithPath: faviconsFolder)
|
|
||||||
try! FileManager.default.createDirectory(at: faviconsFolderURL, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
faviconDownloader = FaviconDownloader(folder: faviconsFolder)
|
|
||||||
|
|
||||||
let imagesFolder = (cacheFolder as NSString).appendingPathComponent("Images")
|
|
||||||
let imagesFolderURL = URL(fileURLWithPath: imagesFolder)
|
|
||||||
try! FileManager.default.createDirectory(at: imagesFolderURL, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
imageDownloader = ImageDownloader(folder: imagesFolder)
|
|
||||||
|
|
||||||
authorAvatarDownloader = AuthorAvatarDownloader(imageDownloader: imageDownloader)
|
|
||||||
webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: cacheFolder)
|
|
||||||
|
|
||||||
updateSortMenuItems()
|
updateSortMenuItems()
|
||||||
updateGroupByFeedMenuItem()
|
updateGroupByFeedMenuItem()
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
|
|
||||||
if isFirstRun {
|
if isFirstRun {
|
||||||
mainWindowController?.window?.center()
|
mainWindowController?.window?.center()
|
||||||
}
|
}
|
||||||
@ -332,19 +352,35 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Main Window
|
// MARK: Main Window
|
||||||
func windowControllerWithName(_ storyboardName: String) -> NSWindowController {
|
|
||||||
|
|
||||||
|
func createMainWindowController() -> MainWindowController {
|
||||||
|
let controller = windowControllerWithName("MainWindow") as! MainWindowController
|
||||||
|
mainWindowControllers.append(controller)
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowControllerWithName(_ storyboardName: String) -> NSWindowController {
|
||||||
let storyboard = NSStoryboard(name: NSStoryboard.Name(storyboardName), bundle: nil)
|
let storyboard = NSStoryboard(name: NSStoryboard.Name(storyboardName), bundle: nil)
|
||||||
return storyboard.instantiateInitialController()! as! NSWindowController
|
return storyboard.instantiateInitialController()! as! NSWindowController
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAndShowMainWindow() {
|
@discardableResult
|
||||||
|
func createAndShowMainWindow() -> NSWindow? {
|
||||||
|
let controller = createMainWindowController()
|
||||||
|
controller.showWindow(self)
|
||||||
|
|
||||||
if mainWindowController == nil {
|
if let window = controller.window {
|
||||||
mainWindowController = createReaderWindow()
|
window.restorationClass = Self.self
|
||||||
|
window.identifier = NSUserInterfaceItemIdentifier(rawValue: WindowRestorationIdentifiers.mainWindow)
|
||||||
}
|
}
|
||||||
|
|
||||||
mainWindowController!.showWindow(self)
|
return controller.window
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAndShowMainWindowIfNecessary() {
|
||||||
|
if mainWindowController == nil {
|
||||||
|
createAndShowMainWindow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: NSUserInterfaceValidations
|
// MARK: NSUserInterfaceValidations
|
||||||
@ -388,8 +424,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
|
|
||||||
// MARK: Add Feed
|
// MARK: Add Feed
|
||||||
func addFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) {
|
func addFeed(_ urlString: String?, name: String? = nil, account: Account? = nil, folder: Folder? = nil) {
|
||||||
|
createAndShowMainWindowIfNecessary()
|
||||||
|
|
||||||
createAndShowMainWindow()
|
|
||||||
if mainWindowController!.isDisplayingSheet {
|
if mainWindowController!.isDisplayingSheet {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -405,7 +441,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
|
|
||||||
// MARK: - Actions
|
// MARK: - Actions
|
||||||
@IBAction func showPreferences(_ sender: Any?) {
|
@IBAction func showPreferences(_ sender: Any?) {
|
||||||
|
|
||||||
if preferencesWindowController == nil {
|
if preferencesWindowController == nil {
|
||||||
preferencesWindowController = windowControllerWithName("Preferences")
|
preferencesWindowController = windowControllerWithName("Preferences")
|
||||||
}
|
}
|
||||||
@ -413,30 +448,30 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
preferencesWindowController!.showWindow(self)
|
preferencesWindowController!.showWindow(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func showMainWindow(_ sender: Any?) {
|
@IBAction func newMainWindow(_ sender: Any?) {
|
||||||
|
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func refreshAll(_ sender: Any?) {
|
@IBAction func showMainWindow(_ sender: Any?) {
|
||||||
|
createAndShowMainWindowIfNecessary()
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func refreshAll(_ sender: Any?) {
|
||||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present)
|
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func showAddFeedWindow(_ sender: Any?) {
|
@IBAction func showAddFeedWindow(_ sender: Any?) {
|
||||||
|
|
||||||
addFeed(nil)
|
addFeed(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func showAddFolderWindow(_ sender: Any?) {
|
@IBAction func showAddFolderWindow(_ sender: Any?) {
|
||||||
|
createAndShowMainWindowIfNecessary()
|
||||||
createAndShowMainWindow()
|
|
||||||
showAddFolderSheetOnWindow(mainWindowController!.window!)
|
showAddFolderSheetOnWindow(mainWindowController!.window!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func showKeyboardShortcutsWindow(_ sender: Any?) {
|
@IBAction func showKeyboardShortcutsWindow(_ sender: Any?) {
|
||||||
|
|
||||||
if keyboardShortcutsWindowController == nil {
|
if keyboardShortcutsWindowController == nil {
|
||||||
|
|
||||||
keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("Keyboard Shortcuts", comment: "window title"))
|
keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("Keyboard Shortcuts", comment: "window title"))
|
||||||
let htmlFile = Bundle(for: type(of: self)).path(forResource: "KeyboardShortcuts", ofType: "html")!
|
let htmlFile = Bundle(for: type(of: self)).path(forResource: "KeyboardShortcuts", ofType: "html")!
|
||||||
keyboardShortcutsWindowController?.displayContents(of: htmlFile)
|
keyboardShortcutsWindowController?.displayContents(of: htmlFile)
|
||||||
@ -447,6 +482,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
let minSize = NSSize(width: 400, height: 400)
|
let minSize = NSSize(width: 400, height: 400)
|
||||||
window.setPointAndSizeAdjustingForScreen(point: point, size: size, minimumSize: minSize)
|
window.setPointAndSizeAdjustingForScreen(point: point, size: size, minimumSize: minSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboardShortcutsWindowController!.showWindow(self)
|
keyboardShortcutsWindowController!.showWindow(self)
|
||||||
@ -467,7 +503,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func importOPMLFromFile(_ sender: Any?) {
|
@IBAction func importOPMLFromFile(_ sender: Any?) {
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
if mainWindowController!.isDisplayingSheet {
|
if mainWindowController!.isDisplayingSheet {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -477,7 +513,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func importNNW3FromFile(_ sender: Any?) {
|
@IBAction func importNNW3FromFile(_ sender: Any?) {
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
if mainWindowController!.isDisplayingSheet {
|
if mainWindowController!.isDisplayingSheet {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -485,7 +521,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func exportOPML(_ sender: Any?) {
|
@IBAction func exportOPML(_ sender: Any?) {
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
if mainWindowController!.isDisplayingSheet {
|
if mainWindowController!.isDisplayingSheet {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -565,19 +601,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||||||
|
|
||||||
@IBAction func gotoToday(_ sender: Any?) {
|
@IBAction func gotoToday(_ sender: Any?) {
|
||||||
|
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
mainWindowController!.gotoToday(sender)
|
mainWindowController!.gotoToday(sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func gotoAllUnread(_ sender: Any?) {
|
@IBAction func gotoAllUnread(_ sender: Any?) {
|
||||||
|
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
mainWindowController!.gotoAllUnread(sender)
|
mainWindowController!.gotoAllUnread(sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func gotoStarred(_ sender: Any?) {
|
@IBAction func gotoStarred(_ sender: Any?) {
|
||||||
|
|
||||||
createAndShowMainWindow()
|
createAndShowMainWindowIfNecessary()
|
||||||
mainWindowController!.gotoStarred(sender)
|
mainWindowController!.gotoStarred(sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,11 +669,6 @@ private extension AppDelegate {
|
|||||||
syncTimer?.fireOldTimer()
|
syncTimer?.fireOldTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createReaderWindow() -> MainWindowController {
|
|
||||||
|
|
||||||
return windowControllerWithName("MainWindow") as! MainWindowController
|
|
||||||
}
|
|
||||||
|
|
||||||
func objectsForInspector() -> [Any]? {
|
func objectsForInspector() -> [Any]? {
|
||||||
|
|
||||||
guard let window = NSApplication.shared.mainWindow, let windowController = window.windowController as? MainWindowController else {
|
guard let window = NSApplication.shared.mainWindow, let windowController = window.windowController as? MainWindowController else {
|
||||||
@ -686,3 +717,15 @@ extension AppDelegate : ScriptingAppDelegate {
|
|||||||
return self.scriptingMainWindowController?.scriptingSelectedArticles ?? []
|
return self.scriptingMainWindowController?.scriptingSelectedArticles ?? []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
completionHandler(mainWindow, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -79,6 +79,13 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||||
|
<menuItem title="New Window" keyEquivalent="n" id="pGg-Gc-PU2">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="newMainWindow:" target="Ady-hI-5gd" id="esB-AD-W2m"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="MFJ-WG-3fx"/>
|
||||||
<menuItem title="Refresh" keyEquivalent="r" id="Veh-SV-KWy">
|
<menuItem title="Refresh" keyEquivalent="r" id="Veh-SV-KWy">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="refreshAll:" target="Ady-hI-5gd" id="gIc-Zj-9tB"/>
|
<action selector="refreshAll:" target="Ady-hI-5gd" id="gIc-Zj-9tB"/>
|
||||||
|
@ -131,20 +131,6 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
|||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
|
|
||||||
// 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()
|
|
||||||
// }
|
|
||||||
|
|
||||||
@objc func applicationWillTerminate(_ note: Notification) {
|
@objc func applicationWillTerminate(_ note: Notification) {
|
||||||
saveState()
|
saveState()
|
||||||
window?.saveFrame(usingName: windowAutosaveName)
|
window?.saveFrame(usingName: windowAutosaveName)
|
||||||
@ -460,9 +446,32 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
|||||||
// MARK: NSWindowDelegate
|
// MARK: NSWindowDelegate
|
||||||
|
|
||||||
extension MainWindowController: NSWindowDelegate {
|
extension MainWindowController: NSWindowDelegate {
|
||||||
|
|
||||||
|
func window(_ window: NSWindow, willEncodeRestorableState state: NSCoder) {
|
||||||
|
|
||||||
|
if let sidebarReadFiltered = sidebarViewController?.isReadFiltered {
|
||||||
|
state.encode(sidebarReadFiltered, forKey: UserInfoKey.readFeedsFilterState)
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveSplitViewState(to: state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func window(_ window: NSWindow, didDecodeRestorableState state: NSCoder) {
|
||||||
|
|
||||||
|
let sidebarReadFiltered = state.decodeBool(forKey: UserInfoKey.readFeedsFilterState)
|
||||||
|
sidebarViewController?.isReadFiltered = sidebarReadFiltered
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
|
||||||
func windowWillClose(_ notification: Notification) {
|
func windowWillClose(_ notification: Notification) {
|
||||||
detailViewController?.stopMediaPlayback()
|
detailViewController?.stopMediaPlayback()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - SidebarDelegate
|
// MARK: - SidebarDelegate
|
||||||
@ -489,6 +498,11 @@ extension MainWindowController: SidebarDelegate {
|
|||||||
}
|
}
|
||||||
return timelineViewController.unreadCount
|
return timelineViewController.unreadCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sidebarInvalidateRestorableState(_: SidebarViewController) {
|
||||||
|
invalidateRestorableState()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - TimelineContainerViewControllerDelegate
|
// MARK: - TimelineContainerViewControllerDelegate
|
||||||
|
@ -15,6 +15,7 @@ import RSCore
|
|||||||
protocol SidebarDelegate: class {
|
protocol SidebarDelegate: class {
|
||||||
func sidebarSelectionDidChange(_: SidebarViewController, selectedObjects: [AnyObject]?)
|
func sidebarSelectionDidChange(_: SidebarViewController, selectedObjects: [AnyObject]?)
|
||||||
func unreadCount(for: AnyObject) -> Int
|
func unreadCount(for: AnyObject) -> Int
|
||||||
|
func sidebarInvalidateRestorableState(_: SidebarViewController)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate, UndoableCommandRunner {
|
@objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate, UndoableCommandRunner {
|
||||||
@ -31,9 +32,17 @@ protocol SidebarDelegate: class {
|
|||||||
lazy var dataSource: SidebarOutlineDataSource = {
|
lazy var dataSource: SidebarOutlineDataSource = {
|
||||||
return SidebarOutlineDataSource(treeController: treeController)
|
return SidebarOutlineDataSource(treeController: treeController)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var isReadFiltered: Bool {
|
var isReadFiltered: Bool {
|
||||||
|
get {
|
||||||
return treeControllerDelegate.isReadFiltered
|
return treeControllerDelegate.isReadFiltered
|
||||||
}
|
}
|
||||||
|
set {
|
||||||
|
treeControllerDelegate.isReadFiltered = newValue
|
||||||
|
delegate?.sidebarInvalidateRestorableState(self)
|
||||||
|
rebuildTreeAndRestoreSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var undoableCommands = [UndoableCommand]()
|
var undoableCommands = [UndoableCommand]()
|
||||||
private var animatingChanges = false
|
private var animatingChanges = false
|
||||||
@ -355,11 +364,10 @@ protocol SidebarDelegate: class {
|
|||||||
|
|
||||||
func toggleReadFilter() {
|
func toggleReadFilter() {
|
||||||
if treeControllerDelegate.isReadFiltered {
|
if treeControllerDelegate.isReadFiltered {
|
||||||
treeControllerDelegate.isReadFiltered = false
|
isReadFiltered = false
|
||||||
} else {
|
} else {
|
||||||
treeControllerDelegate.isReadFiltered = true
|
isReadFiltered = true
|
||||||
}
|
}
|
||||||
rebuildTreeAndRestoreSelection()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user