NetNewsWire/Evergreen/MainWindow/MainWindowController.swift

361 lines
8.6 KiB
Swift
Raw Normal View History

2017-05-27 19:43:27 +02:00
//
// MainWindowController.swift
// Evergreen
//
// Created by Brent Simmons on 8/1/15.
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//
import Cocoa
import Data
import Account
2017-05-27 19:43:27 +02:00
private let kWindowFrameKey = "MainWindow"
class MainWindowController : NSWindowController, NSUserInterfaceValidations {
// MARK: NSWindowController
2017-10-06 03:17:07 +02:00
private let windowAutosaveName = NSWindow.FrameAutosaveName(rawValue: kWindowFrameKey)
2017-10-19 06:53:45 +02:00
private var unreadCount: Int = 0 {
didSet {
if unreadCount != oldValue {
updateWindowTitle()
}
}
}
2017-10-06 03:17:07 +02:00
2017-05-27 19:43:27 +02:00
override func windowDidLoad() {
super.windowDidLoad()
if !AppDefaults.shared.showTitleOnMainWindow {
window?.titleVisibility = .hidden
}
2017-10-06 03:17:07 +02:00
window?.setFrameUsingName(windowAutosaveName, force: true)
if AppDefaults.shared.isFirstRun {
if let window = window, let screen = window.screen {
let width: CGFloat = 1280.0
let height: CGFloat = 768.0
let insetX: CGFloat = 192.0
let insetY: CGFloat = 96.0
window.setContentSize(NSSize(width: width, height: height))
window.setFrameTopLeftPoint(NSPoint(x: insetX, y: screen.visibleFrame.maxY - insetY))
}
}
2017-05-27 19:43:27 +02:00
detailSplitViewItem?.minimumThickness = 384
2017-09-18 01:30:45 +02:00
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillTerminate(_:)), name: NSApplication.willTerminateNotification, object: nil)
2017-05-27 19:43:27 +02:00
NotificationCenter.default.addObserver(self, selector: #selector(appNavigationKeyPressed(_:)), name: .AppNavigationKeyPressed, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(refreshProgressDidChange(_:)), name: .AccountRefreshDidBegin, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(refreshProgressDidChange(_:)), name: .AccountRefreshDidFinish, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(refreshProgressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
2017-10-19 06:53:45 +02:00
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
DispatchQueue.main.async {
self.updateWindowTitle()
2017-05-27 19:43:27 +02:00
}
2017-10-19 06:53:45 +02:00
}
2017-05-27 19:43:27 +02:00
// MARK: Notifications
2017-09-17 21:54:08 +02:00
@objc func applicationWillTerminate(_ note: Notification) {
2017-05-27 19:43:27 +02:00
2017-10-06 03:17:07 +02:00
window?.saveFrame(usingName: windowAutosaveName)
2017-05-27 19:43:27 +02:00
}
2017-09-17 21:54:08 +02:00
@objc func appNavigationKeyPressed(_ note: Notification) {
2017-05-27 19:43:27 +02:00
guard let navigationKey = note.userInfo?[UserInfoKey.navigationKeyPressed] as? Int else {
2017-05-27 19:43:27 +02:00
return
}
guard let contentView = window?.contentView, let view = note.object as? NSView, view.isDescendant(of: contentView) else {
return
}
if navigationKey == NSRightArrowFunctionKey {
handleRightArrowFunctionKey(in: view)
}
if navigationKey == NSLeftArrowFunctionKey {
handleLeftArrowFunctionKey(in: view)
}
2017-05-27 19:43:27 +02:00
}
2017-09-17 21:54:08 +02:00
@objc func refreshProgressDidChange(_ note: Notification) {
2017-05-27 19:43:27 +02:00
performSelectorCoalesced(#selector(MainWindowController.makeToolbarValidate(_:)), with: nil, delay: 0.1)
2017-05-27 19:43:27 +02:00
}
2017-10-19 06:53:45 +02:00
@objc func unreadCountDidChange(_ note: Notification) {
if note.object is AccountManager {
unreadCount = AccountManager.shared.unreadCount
}
}
2017-05-27 19:43:27 +02:00
// MARK: Toolbar
2017-10-06 05:03:35 +02:00
@objc func makeToolbarValidate(_ sender: Any) {
2017-05-27 19:43:27 +02:00
window?.toolbar?.validateVisibleItems()
}
2017-05-27 19:43:27 +02:00
// MARK: NSUserInterfaceValidations
public func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
if item.action == #selector(openArticleInBrowser(_:)) {
return currentLink != nil
}
if item.action == #selector(nextUnread(_:)) {
return canGoToNextUnread()
}
if item.action == #selector(markAllAsRead(_:)) {
return canMarkAllAsRead()
}
2017-11-06 06:27:34 +01:00
if item.action == #selector(markRead(_:)) {
return canMarkRead()
}
2017-05-27 19:43:27 +02:00
return true
}
// MARK: - Actions
@IBAction func scrollOrGoToNextUnread(_ sender: Any?) {
2017-12-20 22:39:31 +01:00
guard let detailViewController = detailViewController else {
return
}
2017-12-20 22:39:31 +01:00
detailViewController.canScrollDown { (canScroll) in
canScroll ? detailViewController.scrollPageDown(sender) : self.nextUnread(sender)
}
}
@IBAction func showAddFolderWindow(_ sender: Any) {
appDelegate.showAddFolderSheetOnWindow(window!)
}
@IBAction func openArticleInBrowser(_ sender: Any?) {
2017-05-27 19:43:27 +02:00
if let link = currentLink {
Browser.open(link)
2017-05-27 19:43:27 +02:00
}
}
@IBAction func openInBrowser(_ sender: Any?) {
openArticleInBrowser(sender)
}
@IBAction func nextUnread(_ sender: Any?) {
2017-05-27 19:43:27 +02:00
guard let timelineViewController = timelineViewController, let sidebarViewController = sidebarViewController else {
return
}
func makeTimelineViewFirstResponder() {
2017-10-19 06:53:45 +02:00
2017-05-27 19:43:27 +02:00
window!.makeFirstResponderUnlessDescendantIsFirstResponder(timelineViewController.tableView)
}
if timelineViewController.canGoToNextUnread() {
timelineViewController.goToNextUnread()
makeTimelineViewFirstResponder()
}
else if sidebarViewController.canGoToNextUnread() {
sidebarViewController.goToNextUnread()
makeTimelineViewFirstResponder()
}
}
@IBAction func markAllAsRead(_ sender: Any?) {
2017-05-27 19:43:27 +02:00
timelineViewController?.markAllAsRead()
}
2017-11-06 06:27:34 +01:00
@IBAction func markRead(_ sender: Any?) {
2017-11-06 06:27:34 +01:00
timelineViewController?.markSelectedArticlesAsRead(sender)
2017-11-06 06:27:34 +01:00
}
@IBAction func markUnread(_ sender: Any?) {
timelineViewController?.markSelectedArticlesAsUnread(sender)
}
@IBAction func markAllAsReadAndGoToNextUnread(_ sender: Any?) {
markAllAsRead(sender)
nextUnread(sender)
}
@IBAction func markUnreadAndGoToNextUnread(_ sender: Any?) {
markUnread(sender)
nextUnread(sender)
}
@IBAction func markReadAndGoToNextUnread(_ sender: Any?) {
markUnread(sender)
nextUnread(sender)
}
@IBAction func toggleSidebar(_ sender: Any?) {
2017-05-27 19:43:27 +02:00
splitViewController!.toggleSidebar(sender)
}
2017-11-17 03:23:07 +01:00
@IBAction func markOlderArticlesAsRead(_ sender: Any?) {
2017-11-17 03:23:07 +01:00
appDelegate.markOlderArticlesAsRead(with: window!)
2017-11-17 03:23:07 +01:00
}
2017-11-20 01:28:26 +01:00
@IBAction func markEverywhereAsRead(_ sender: Any?) {
appDelegate.markEverywhereAsRead(with: window!)
}
@IBAction func navigateToTimeline(_ sender: Any?) {
timelineViewController?.focus()
}
@IBAction func navigateToSidebar(_ sender: Any?) {
sidebarViewController?.focus()
}
@IBAction func goToPreviousSubscription(_ sender: Any?) {
sidebarViewController?.outlineView.selectPreviousRow(sender)
}
@IBAction func goToNextSubscription(_ sender: Any?) {
sidebarViewController?.outlineView.selectNextRow(sender)
}
2017-05-27 19:43:27 +02:00
}
2017-10-06 05:03:35 +02:00
// MARK: - Private
2017-05-27 19:43:27 +02:00
private extension MainWindowController {
var splitViewController: NSSplitViewController? {
get {
guard let viewController = contentViewController else {
return nil
}
return viewController.childViewControllers.first as? NSSplitViewController
}
}
var sidebarViewController: SidebarViewController? {
get {
return splitViewController?.splitViewItems[0].viewController as? SidebarViewController
}
}
var timelineViewController: TimelineViewController? {
get {
return splitViewController?.splitViewItems[1].viewController as? TimelineViewController
}
}
var detailSplitViewItem: NSSplitViewItem? {
2017-10-06 05:03:35 +02:00
get {
return splitViewController?.splitViewItems[2]
}
2017-05-27 19:43:27 +02:00
}
var detailViewController: DetailViewController? {
get {
return splitViewController?.splitViewItems[2].viewController as? DetailViewController
}
}
var selectedArticles: [Article]? {
get {
return timelineViewController?.selectedArticles
}
}
var oneSelectedArticle: Article? {
get {
if let articles = selectedArticles {
return articles.count == 1 ? articles[0] : nil
}
return nil
}
}
var currentLink: String? {
get {
2017-10-06 05:03:35 +02:00
return oneSelectedArticle?.preferredLink
2017-05-27 19:43:27 +02:00
}
}
func canGoToNextUnread() -> Bool {
guard let timelineViewController = timelineViewController, let sidebarViewController = sidebarViewController else {
return false
}
return timelineViewController.canGoToNextUnread() || sidebarViewController.canGoToNextUnread()
}
func canMarkAllAsRead() -> Bool {
return timelineViewController?.canMarkAllAsRead() ?? false
}
2017-10-19 06:53:45 +02:00
2017-11-06 06:27:34 +01:00
func canMarkRead() -> Bool {
return timelineViewController?.canMarkSelectedArticlesAsRead() ?? false
}
2017-10-19 06:53:45 +02:00
func updateWindowTitle() {
if unreadCount < 1 {
window?.title = appDelegate.appName!
2017-10-19 06:53:45 +02:00
}
else if unreadCount > 0 {
window?.title = "\(appDelegate.appName!) (\(unreadCount))"
2017-10-19 06:53:45 +02:00
}
}
// MARK: - Navigation
func handleRightArrowFunctionKey(in view: NSView) {
guard let outlineView = sidebarViewController?.outlineView, view === outlineView, let timelineViewController = timelineViewController else {
return
}
timelineViewController.focus()
}
func handleLeftArrowFunctionKey(in view: NSView) {
guard let timelineView = timelineViewController?.tableView, view === timelineView, let sidebarViewController = sidebarViewController else {
return
}
sidebarViewController.focus()
}
2017-05-27 19:43:27 +02:00
}