Make a bunch of progress on keyboard commands.

This commit is contained in:
Brent Simmons 2017-12-20 12:59:31 -08:00
parent b0fc2e7391
commit 6879c172c2
11 changed files with 247 additions and 140 deletions

View File

@ -18,6 +18,11 @@
842E45E51ED8C6B7000A8B52 /* MainWindowSplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842E45E41ED8C6B7000A8B52 /* MainWindowSplitView.swift */; };
842E45E71ED8C747000A8B52 /* DB5.plist in Resources */ = {isa = PBXBuildFile; fileRef = 842E45E61ED8C747000A8B52 /* DB5.plist */; };
84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84411E701FE5FBFA004B527F /* SmallIconProvider.swift */; };
844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B581FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift */; };
844B5B5B1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B5A1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift */; };
844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; };
844B5B671FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B661FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift */; };
844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */; };
84513F901FAA63950023A1A9 /* FeedListControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84513F8F1FAA63950023A1A9 /* FeedListControlsView.swift */; };
845213231FCA5B11003B6E93 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845213221FCA5B10003B6E93 /* ImageDownloader.swift */; };
845A29091FC74B8E007B49E3 /* SingleFaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */; };
@ -419,6 +424,11 @@
842E45E41ED8C6B7000A8B52 /* MainWindowSplitView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowSplitView.swift; sourceTree = "<group>"; };
842E45E61ED8C747000A8B52 /* DB5.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = DB5.plist; path = Evergreen/Resources/DB5.plist; sourceTree = "<group>"; };
84411E701FE5FBFA004B527F /* SmallIconProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallIconProvider.swift; sourceTree = "<group>"; };
844B5B581FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarKeyboardDelegate.swift; sourceTree = "<group>"; };
844B5B5A1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineKeyboardDelegate.swift; sourceTree = "<group>"; };
844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = GlobalKeyboardShortcuts.plist; sourceTree = "<group>"; };
844B5B661FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWIndowKeyboardHandler.swift; sourceTree = "<group>"; };
844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = SidebarKeyboardShortcuts.plist; sourceTree = "<group>"; };
84513F8F1FAA63950023A1A9 /* FeedListControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListControlsView.swift; sourceTree = "<group>"; };
845213221FCA5B10003B6E93 /* ImageDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageDownloader.swift; sourceTree = "<group>"; };
845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleFaviconDownloader.swift; sourceTree = "<group>"; };
@ -572,6 +582,7 @@
842E45E21ED8C681000A8B52 /* KeyboardDelegateProtocol.swift */,
849A975D1ED9EB72007D329B /* MainWindowController.swift */,
842E45E41ED8C6B7000A8B52 /* MainWindowSplitView.swift */,
844B5B6B1FEA224B00C7C76A /* Keyboard */,
849A975F1ED9EB95007D329B /* Sidebar */,
849A97681ED9EBC8007D329B /* Timeline */,
849A977C1ED9EC42007D329B /* Detail */,
@ -583,6 +594,32 @@
path = Evergreen/MainWindow;
sourceTree = "<group>";
};
844B5B6A1FEA224000C7C76A /* Keyboard */ = {
isa = PBXGroup;
children = (
844B5B581FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift */,
844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */,
);
path = Keyboard;
sourceTree = "<group>";
};
844B5B6B1FEA224B00C7C76A /* Keyboard */ = {
isa = PBXGroup;
children = (
844B5B661FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift */,
844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */,
);
path = Keyboard;
sourceTree = "<group>";
};
844B5B6C1FEA282400C7C76A /* Keyboard */ = {
isa = PBXGroup;
children = (
844B5B5A1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift */,
);
path = Keyboard;
sourceTree = "<group>";
};
845213211FCA5B10003B6E93 /* Images */ = {
isa = PBXGroup;
children = (
@ -685,6 +722,7 @@
849A97631ED9EB96007D329B /* UnreadCountView.swift */,
845F52EC1FB2B9FC00C10BF0 /* FeedPasteboardWriter.swift */,
849A97821ED9EC63007D329B /* SidebarStatusBarView.swift */,
844B5B6A1FEA224000C7C76A /* Keyboard */,
845A29251FC928C7007B49E3 /* Cell */,
);
path = Sidebar;
@ -697,6 +735,7 @@
84F204DF1FAACBB30076E152 /* ArticleArray.swift */,
849A97691ED9EBC8007D329B /* TimelineTableRowView.swift */,
849A976A1ED9EBC8007D329B /* TimelineTableView.swift */,
844B5B6C1FEA282400C7C76A /* Keyboard */,
84E95D231FB1087500552D99 /* ArticlePasteboardWriter.swift */,
8414AD241FCF5A1E00955102 /* TimelineHeaderView.swift */,
849A976F1ED9EC04007D329B /* Cell */,
@ -1316,11 +1355,13 @@
files = (
84EB381F1FBA8B9F000D2111 /* KeyboardShortcuts.html in Resources */,
849A97951ED9EF7A007D329B /* IndeterminateProgressWindow.xib in Resources */,
844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */,
849A978F1ED9EE72007D329B /* DefaultFeeds.plist in Resources */,
849A979D1ED9EFEB007D329B /* template.html in Resources */,
849A97A91ED9F9AA007D329B /* AddFeedSheet.xib in Resources */,
84AFBB3E1FBE770200BA41CF /* PanicButtonWindow.xib in Resources */,
842E45E71ED8C747000A8B52 /* DB5.plist in Resources */,
844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */,
849A97AC1ED9F9BC007D329B /* AddFolderSheet.xib in Resources */,
849A97AF1ED9FA08007D329B /* FeedList.storyboard in Resources */,
84E95CF71FABB3C800552D99 /* FeedList.plist in Resources */,
@ -1351,6 +1392,7 @@
84513F901FAA63950023A1A9 /* FeedListControlsView.swift in Sources */,
84E46C7D1F75EF7B005ECFB3 /* AppDefaults.swift in Sources */,
842E45CE1ED8C308000A8B52 /* AppNotifications.swift in Sources */,
844B5B5B1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift in Sources */,
84DAEE321F870B390058304B /* DockBadge.swift in Sources */,
842E45DD1ED8C54B000A8B52 /* Browser.swift in Sources */,
842E45E31ED8C681000A8B52 /* KeyboardDelegateProtocol.swift in Sources */,
@ -1389,6 +1431,7 @@
84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */,
845213231FCA5B11003B6E93 /* ImageDownloader.swift in Sources */,
849A97431ED9EAA9007D329B /* AddFolderWindowController.swift in Sources */,
844B5B671FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift in Sources */,
849A97921ED9EF65007D329B /* IndeterminateProgressWindowController.swift in Sources */,
849A97801ED9EC42007D329B /* DetailViewController.swift in Sources */,
8426119E1FCB6ED40086A189 /* HTMLMetadataDownloader.swift in Sources */,
@ -1408,6 +1451,7 @@
84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */,
84F204DE1FAACB8B0076E152 /* FeedListTimelineViewController.swift in Sources */,
84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */,
844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */,
849A97A31ED9F180007D329B /* FolderTreeControllerDelegate.swift in Sources */,
845A29091FC74B8E007B49E3 /* SingleFaviconDownloader.swift in Sources */,
849A97851ED9ECCD007D329B /* PreferencesWindowController.swift in Sources */,

View File

@ -284,7 +284,7 @@
<rect key="frame" x="0.0" y="0.0" width="166" height="272"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView appearanceType="aqua" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="medium" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="16" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="Evergreen" customModuleProvider="target">
<outlineView appearanceType="aqua" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="24" rowSizeStyle="medium" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="16" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="Evergreen" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="167" height="272"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
@ -352,6 +352,7 @@
<connections>
<outlet property="dataSource" destination="XML-A3-pDn" id="04v-0e-BM6"/>
<outlet property="delegate" destination="XML-A3-pDn" id="fPE-cv-p5c"/>
<outlet property="keyboardDelegate" destination="h5K-zR-cUa" id="BlT-aW-sea"/>
</connections>
</outlineView>
</subviews>
@ -435,6 +436,11 @@
</connections>
</viewController>
<customObject id="Jih-JO-hIE" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<customObject id="h5K-zR-cUa" customClass="SidebarKeyboardDelegate" customModule="Evergreen" customModuleProvider="target">
<connections>
<outlet property="sidebarViewController" destination="XML-A3-pDn" id="kwd-Zc-HJm"/>
</connections>
</customObject>
</objects>
<point key="canvasLocation" x="-74" y="-186"/>
</scene>
@ -547,6 +553,7 @@
<connections>
<outlet property="dataSource" destination="36G-bQ-b96" id="OpB-zC-ItJ"/>
<outlet property="delegate" destination="36G-bQ-b96" id="s1m-42-GQ4"/>
<outlet property="keyboardDelegate" destination="ZOV-xh-WJE" id="HiG-Bz-vD0"/>
</connections>
</tableView>
</subviews>
@ -582,6 +589,11 @@
</connections>
</viewController>
<customObject id="Ebq-4s-EwK" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<customObject id="ZOV-xh-WJE" customClass="TimelineKeyboardDelegate" customModule="Evergreen" customModuleProvider="target">
<connections>
<outlet property="timelineViewController" destination="36G-bQ-b96" id="rED-2Z-kh6"/>
</connections>
</customObject>
</objects>
<point key="canvasLocation" x="62" y="394"/>
</scene>

View File

@ -0,0 +1,36 @@
//
// MainWIndowKeyboardHandler.swift
// Evergreen
//
// Created by Brent Simmons on 12/19/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Cocoa
import RSCore
final class MainWindowKeyboardHandler: KeyboardDelegate {
static let shared = MainWindowKeyboardHandler()
let globalShortcuts: Set<KeyboardShortcut>
init() {
let f = Bundle.main.path(forResource: "GlobalKeyboardShortcuts", ofType: "plist")!
let rawShortcuts = NSArray(contentsOfFile: f)! as! [[String: Any]]
self.globalShortcuts = Set(rawShortcuts.flatMap { KeyboardShortcut(dictionary: $0) })
}
func keydown(_ event: NSEvent, in view: NSView) -> Bool {
let key = KeyboardKey(with: event)
guard let matchingShortcut = KeyboardShortcut.findMatchingShortcut(in: globalShortcuts, key: key) else {
return false
}
matchingShortcut.perform(with: view)
return true
}
}

View File

@ -10,8 +10,8 @@ import Cocoa
let keypadEnter: unichar = 3
protocol KeyboardDelegate: class {
@objc protocol KeyboardDelegate: class {
// Return true if handled.
func handleKeydownEvent(_: NSEvent, sender: AnyObject) -> Bool
func keydown(_: NSEvent, in view: NSView) -> Bool
}

View File

@ -118,21 +118,41 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
return true
}
// MARK: Actions
@IBAction func showAddFolderWindow(_ sender: AnyObject) {
// MARK: - Actions
@IBAction func scrollOrGoToNextUnread(_ sender: Any?) {
// guard let detailViewController = detailViewController else {
// return
// }
//
// if detailViewController.canScrollWebView() {
// detailViewController.scrollPageDown(sender)
// return
// }
nextUnread(sender)
}
@IBAction func showAddFolderWindow(_ sender: Any) {
appDelegate.showAddFolderSheetOnWindow(window!)
}
@IBAction func openArticleInBrowser(_ sender: AnyObject?) {
@IBAction func openArticleInBrowser(_ sender: Any?) {
if let link = currentLink {
Browser.open(link)
}
}
@IBAction func nextUnread(_ sender: AnyObject?) {
@IBAction func openInBrowser(_ sender: Any?) {
openArticleInBrowser(sender)
}
@IBAction func nextUnread(_ sender: Any?) {
guard let timelineViewController = timelineViewController, let sidebarViewController = sidebarViewController else {
return
@ -153,17 +173,28 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
}
}
@IBAction func markAllAsRead(_ sender: AnyObject?) {
@IBAction func markAllAsRead(_ sender: Any?) {
timelineViewController?.markAllAsRead()
}
@IBAction func markRead(_ sender: AnyObject?) {
@IBAction func markRead(_ sender: Any?) {
timelineViewController?.markSelectedArticlesAsRead(sender!)
timelineViewController?.markSelectedArticlesAsRead(sender)
}
@IBAction func toggleSidebar(_ sender: AnyObject?) {
@IBAction func markUnread(_ sender: Any?) {
timelineViewController?.markSelectedArticlesAsUnread(sender)
}
@IBAction func markUnreadAndGoToNextUnread(_ sender: Any?) {
markUnread(sender)
nextUnread(sender)
}
@IBAction func toggleSidebar(_ sender: Any?) {
splitViewController!.toggleSidebar(sender)
}

View File

@ -0,0 +1,42 @@
//
// SidebarKeyboardDelegate.swift
// Evergreen
//
// Created by Brent Simmons on 12/19/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Cocoa
import RSCore
@objc final class SidebarKeyboardDelegate: NSObject, KeyboardDelegate {
@IBOutlet weak var sidebarViewController: SidebarViewController?
let shortcuts: Set<KeyboardShortcut>
override init() {
let f = Bundle.main.path(forResource: "SidebarKeyboardShortcuts", ofType: "plist")!
let rawShortcuts = NSArray(contentsOfFile: f)! as! [[String: Any]]
self.shortcuts = Set(rawShortcuts.flatMap { KeyboardShortcut(dictionary: $0) })
super.init()
}
func keydown(_ event: NSEvent, in view: NSView) -> Bool {
if MainWindowKeyboardHandler.shared.keydown(event, in: view) {
return true
}
let key = KeyboardKey(with: event)
guard let matchingShortcut = KeyboardShortcut.findMatchingShortcut(in: shortcuts, key: key) else {
return false
}
matchingShortcut.perform(with: view)
return true
}
}

View File

@ -13,47 +13,17 @@ import RSTree
class SidebarOutlineView : NSOutlineView {
weak var sidebarViewController: SidebarViewController?
@IBOutlet var keyboardDelegate: KeyboardDelegate!
//MARK: NSResponder
override func keyDown(with event: NSEvent) {
guard !event.rs_keyIsModified() else {
super.keyDown(with: event)
return
}
let ch = Int(event.rs_unmodifiedCharacter())
if ch == NSNotFound {
super.keyDown(with: event)
return
}
var isNavigationKey = false
var keyHandled = false
switch(ch) {
case NSRightArrowFunctionKey:
isNavigationKey = true
keyHandled = true
case NSDeleteFunctionKey, Int(kDeleteKeyCode):
keyHandled = true
sidebarViewController?.delete(event)
default:
keyHandled = false
}
if isNavigationKey {
NotificationCenter.default.post(name: .AppNavigationKeyPressed, object: self, userInfo: [UserInfoKey.navigationKeyPressed: ch])
if keyboardDelegate.keydown(event, in: self) {
return
}
if !keyHandled {
super.keyDown(with: event)
}
super.keyDown(with: event)
}
override func frameOfCell(atColumn column: Int, row: Int) -> NSRect {

View File

@ -125,6 +125,14 @@ import RSCore
animatingChanges = false
}
@IBAction func openInBrowser(_ sender: Any?) {
guard let feed = singleSelectedFeed, let homePageURL = feed.homePageURL else {
return
}
Browser.open(homePageURL)
}
// MARK: Navigation
@ -243,14 +251,26 @@ import RSCore
private extension SidebarViewController {
var selectedNodes: [Node] {
get {
if let nodes = outlineView.selectedItems as? [Node] {
return nodes
}
return [Node]()
if let nodes = outlineView.selectedItems as? [Node] {
return nodes
}
return [Node]()
}
var singleSelectedNode: Node? {
guard selectedNodes.count == 1 else {
return nil
}
return selectedNodes.first!
}
var singleSelectedFeed: Feed? {
guard let node = singleSelectedNode else {
return nil
}
return node.representedObject as? Feed
}
func rebuildTreeAndReloadDataIfNeeded() {
if !animatingChanges && !BatchUpdate.shared.isPerforming {

View File

@ -0,0 +1,26 @@
//
// TimelineKeyboardDelegate.swift
// Evergreen
//
// Created by Brent Simmons on 12/19/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Cocoa
import RSCore
// Doesnt have any shortcuts of its own  theyre all in MainWindowKeyboardHandler.
@objc final class TimelineKeyboardDelegate: NSObject, KeyboardDelegate {
@IBOutlet weak var timelineViewController: TimelineViewController?
override init() {
super.init()
}
func keydown(_ event: NSEvent, in view: NSView) -> Bool {
return MainWindowKeyboardHandler.shared.keydown(event, in: view)
}
}

View File

@ -10,18 +10,15 @@ import Cocoa
class TimelineTableView: NSTableView {
weak var keyboardDelegate: KeyboardDelegate?
@IBOutlet var keyboardDelegate: KeyboardDelegate!
//MARK: NSResponder
override func keyDown(with event: NSEvent) {
if let keyboardDelegate = keyboardDelegate {
if keyboardDelegate.handleKeydownEvent(event, sender: self) {
return;
}
if keyboardDelegate.keydown(event, in: self) {
return
}
super.keyDown(with: event)
}

View File

@ -12,7 +12,7 @@ import RSTextDrawing
import Data
import Account
class TimelineViewController: NSViewController, KeyboardDelegate, UndoableCommandRunner {
class TimelineViewController: NSViewController, UndoableCommandRunner {
@IBOutlet var tableView: TimelineTableView!
@ -22,6 +22,12 @@ class TimelineViewController: NSViewController, KeyboardDelegate, UndoableComman
}
}
var hasAtLeastOneSelectedArticle: Bool {
get {
return tableView.selectedRow != -1
}
}
var undoableCommands = [UndoableCommand]()
private var cellAppearance: TimelineCellAppearance!
private var showFeedNames = false
@ -68,7 +74,6 @@ class TimelineViewController: NSViewController, KeyboardDelegate, UndoableComman
tableView.rowHeight = calculateRowHeight()
tableView.target = self
tableView.doubleAction = #selector(openArticleInBrowser(_:))
tableView.keyboardDelegate = self
tableView.setDraggingSourceOperationMask(.copy, forLocal: false)
if !didRegisterForNotifications {
@ -159,7 +164,7 @@ class TimelineViewController: NSViewController, KeyboardDelegate, UndoableComman
}
}
@IBAction func markSelectedArticlesAsRead(_ sender: AnyObject?) {
@IBAction func markSelectedArticlesAsRead(_ sender: Any?) {
guard let undoManager = undoManager, let markReadCommand = MarkReadOrUnreadCommand(initialArticles: selectedArticles, markingRead: true, undoManager: undoManager) else {
return
@ -167,7 +172,7 @@ class TimelineViewController: NSViewController, KeyboardDelegate, UndoableComman
runCommand(markReadCommand)
}
@IBAction func markSelectedArticlesAsUnread(_ sender: AnyObject) {
@IBAction func markSelectedArticlesAsUnread(_ sender: Any?) {
guard let undoManager = undoManager, let markUnreadCommand = MarkReadOrUnreadCommand(initialArticles: selectedArticles, markingRead: false, undoManager: undoManager) else {
return
@ -250,76 +255,6 @@ class TimelineViewController: NSViewController, KeyboardDelegate, UndoableComman
}
}
// MARK: - KeyboardDelegate
func handleKeydownEvent(_ event: NSEvent, sender: AnyObject) -> Bool {
guard !event.rs_keyIsModified() else {
return false
}
let ch = Int(event.rs_unmodifiedCharacter())
if ch == NSNotFound {
return false
}
let hasSelectedArticle = hasAtLeastOneSelectedArticle
var keyHandled = false
var isNavigationKey = false
var shouldOpenInBrowser = false
switch(ch) {
case KeyboardConstant.lineFeedKey:
shouldOpenInBrowser = true
keyHandled = true
case KeyboardConstant.returnKey:
shouldOpenInBrowser = true
keyHandled = true
case "r".keyboardIntegerValue:
markSelectedArticlesAsRead(sender)
keyHandled = true
case "u".keyboardIntegerValue:
markSelectedArticlesAsUnread(sender)
keyHandled = true
case NSLeftArrowFunctionKey:
isNavigationKey = true
keyHandled = true
default:
keyHandled = false
}
if !keyHandled {
let chUnichar = event.rs_unmodifiedCharacter()
switch(chUnichar) {
case keypadEnter:
shouldOpenInBrowser = true
keyHandled = true
default:
keyHandled = false
}
}
if isNavigationKey {
NotificationCenter.default.post(name: .AppNavigationKeyPressed, object: self.tableView, userInfo: [UserInfoKey.navigationKeyPressed: ch])
}
if shouldOpenInBrowser && hasSelectedArticle {
openArticleInBrowser(self)
}
return keyHandled
}
// MARK: - Reloading Data
private func cellForRowView(_ rowView: NSView) -> NSView? {
@ -501,12 +436,6 @@ extension TimelineViewController: NSTableViewDelegate {
private extension TimelineViewController {
var hasAtLeastOneSelectedArticle: Bool {
get {
return tableView.selectedRow != -1
}
}
func emptyTheTimeline() {
if !articles.isEmpty {