Merge pull request #2540 from danielpunkass/jalkut-skip-mode
Support a new secret user default…
This commit is contained in:
commit
b504c88948
@ -323,13 +323,16 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
||||
NSCursor.setHiddenUntilMouseMoves(true)
|
||||
|
||||
// TODO: handle search mode
|
||||
if timelineViewController.canGoToNextUnread() {
|
||||
goToNextUnreadInTimeline()
|
||||
if timelineViewController.canGoToNextUnread(wrappingToTop: false) {
|
||||
goToNextUnreadInTimeline(wrappingToTop: false)
|
||||
}
|
||||
else if sidebarViewController.canGoToNextUnread() {
|
||||
sidebarViewController.goToNextUnread()
|
||||
if timelineViewController.canGoToNextUnread() {
|
||||
goToNextUnreadInTimeline()
|
||||
else if sidebarViewController.canGoToNextUnread(wrappingToTop: true) {
|
||||
sidebarViewController.goToNextUnread(wrappingToTop: true)
|
||||
|
||||
// If we ended up on the same timelineViewController, we may need to wrap
|
||||
// around to the top of its contents.
|
||||
if timelineViewController.canGoToNextUnread(wrappingToTop: true) {
|
||||
goToNextUnreadInTimeline(wrappingToTop: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -995,13 +998,13 @@ private extension MainWindowController {
|
||||
|
||||
// MARK: - Command Validation
|
||||
|
||||
func canGoToNextUnread() -> Bool {
|
||||
func canGoToNextUnread(wrappingToTop wrapping: Bool = false) -> Bool {
|
||||
|
||||
guard let timelineViewController = currentTimelineViewController, let sidebarViewController = sidebarViewController else {
|
||||
return false
|
||||
}
|
||||
// TODO: handle search mode
|
||||
return timelineViewController.canGoToNextUnread() || sidebarViewController.canGoToNextUnread()
|
||||
return timelineViewController.canGoToNextUnread(wrappingToTop: wrapping) || sidebarViewController.canGoToNextUnread(wrappingToTop: wrapping)
|
||||
}
|
||||
|
||||
func canMarkAllAsRead() -> Bool {
|
||||
@ -1188,14 +1191,14 @@ private extension MainWindowController {
|
||||
|
||||
// MARK: - Misc.
|
||||
|
||||
func goToNextUnreadInTimeline() {
|
||||
func goToNextUnreadInTimeline(wrappingToTop wrapping: Bool) {
|
||||
|
||||
guard let timelineViewController = currentTimelineViewController else {
|
||||
return
|
||||
}
|
||||
|
||||
if timelineViewController.canGoToNextUnread() {
|
||||
timelineViewController.goToNextUnread()
|
||||
if timelineViewController.canGoToNextUnread(wrappingToTop: wrapping) {
|
||||
timelineViewController.goToNextUnread(wrappingToTop: wrapping)
|
||||
makeTimelineViewFirstResponder()
|
||||
}
|
||||
}
|
||||
|
@ -294,15 +294,15 @@ protocol SidebarDelegate: class {
|
||||
|
||||
// MARK: - Navigation
|
||||
|
||||
func canGoToNextUnread() -> Bool {
|
||||
if let _ = nextSelectableRowWithUnreadArticle() {
|
||||
func canGoToNextUnread(wrappingToTop wrapping: Bool = false) -> Bool {
|
||||
if let _ = nextSelectableRowWithUnreadArticle(wrappingToTop: wrapping) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func goToNextUnread() {
|
||||
guard let row = nextSelectableRowWithUnreadArticle() else {
|
||||
func goToNextUnread(wrappingToTop wrapping: Bool = false) {
|
||||
guard let row = nextSelectableRowWithUnreadArticle(wrappingToTop: wrapping) else {
|
||||
assertionFailure("goToNextUnread called before checking if there is a next unread.")
|
||||
return
|
||||
}
|
||||
@ -685,26 +685,42 @@ private extension SidebarViewController {
|
||||
return false
|
||||
}
|
||||
|
||||
func nextSelectableRowWithUnreadArticle() -> Int? {
|
||||
// Skip group items, because they should never be selected.
|
||||
|
||||
let selectedRow = outlineView.selectedRow
|
||||
let numberOfRows = outlineView.numberOfRows
|
||||
var row = selectedRow + 1
|
||||
|
||||
while (row < numberOfRows) {
|
||||
if rowHasAtLeastOneUnreadArticle(row) && !rowIsGroupItem(row) {
|
||||
return row
|
||||
}
|
||||
row += 1
|
||||
func rowIsExpandedFolder(_ row: Int) -> Bool {
|
||||
if let node = nodeForRow(row), outlineView.isItemExpanded(node) {
|
||||
return true
|
||||
}
|
||||
|
||||
row = 0
|
||||
while (row <= selectedRow) {
|
||||
if rowHasAtLeastOneUnreadArticle(row) && !rowIsGroupItem(row) {
|
||||
return false
|
||||
}
|
||||
|
||||
func shouldSkipRow(_ row: Int) -> Bool {
|
||||
let skipExpandedFolders = UserDefaults.standard.bool(forKey: "JalkutRespectFolderExpansionOnNextUnread")
|
||||
|
||||
// Skip group items, because they should never be selected.
|
||||
// Skip expanded folders only if Jalkut's pref is enabled.
|
||||
if rowIsGroupItem(row) || (skipExpandedFolders && rowIsExpandedFolder(row)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func nextSelectableRowWithUnreadArticle(wrappingToTop wrapping: Bool = false) -> Int? {
|
||||
let numberOfRows = outlineView.numberOfRows
|
||||
let startRow = outlineView.selectedRow + 1
|
||||
|
||||
let orderedRows: [Int]
|
||||
if startRow == numberOfRows {
|
||||
// Last item is selected, so start at the beginning if we allow wrapping
|
||||
orderedRows = wrapping ? Array(0..<numberOfRows) : []
|
||||
} else {
|
||||
// Start at the selection and wrap around to the beginning
|
||||
orderedRows = Array(startRow..<numberOfRows) + (wrapping ? Array(0..<startRow) : [])
|
||||
}
|
||||
|
||||
for row in orderedRows {
|
||||
// Skip group items, because they should never be selected.
|
||||
if rowHasAtLeastOneUnreadArticle(row) && !shouldSkipRow(row) {
|
||||
return row
|
||||
}
|
||||
row += 1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -549,7 +549,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
tableView.scrollTo(row: ix)
|
||||
}
|
||||
|
||||
func goToNextUnread() {
|
||||
func goToNextUnread(wrappingToTop wrapping: Bool = false) {
|
||||
guard let ix = indexOfNextUnreadArticle() else {
|
||||
return
|
||||
}
|
||||
@ -558,15 +558,15 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
tableView.scrollTo(row: ix)
|
||||
}
|
||||
|
||||
func canGoToNextUnread() -> Bool {
|
||||
guard let _ = indexOfNextUnreadArticle() else {
|
||||
func canGoToNextUnread(wrappingToTop wrapping: Bool = false) -> Bool {
|
||||
guard let _ = indexOfNextUnreadArticle(wrappingToTop: wrapping) else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func indexOfNextUnreadArticle() -> Int? {
|
||||
return articles.rowOfNextUnreadArticle(tableView.selectedRow)
|
||||
func indexOfNextUnreadArticle(wrappingToTop wrapping: Bool = false) -> Int? {
|
||||
return articles.rowOfNextUnreadArticle(tableView.selectedRow, wrappingToTop: wrapping)
|
||||
}
|
||||
|
||||
func focus() {
|
||||
|
@ -20,18 +20,21 @@ extension Array where Element == Article {
|
||||
return self[row]
|
||||
}
|
||||
|
||||
func rowOfNextUnreadArticle(_ selectedRow: Int) -> Int? {
|
||||
func orderedRowIndexes(fromIndex startIndex: Int, wrappingToTop wrapping: Bool) -> [Int] {
|
||||
if startIndex >= self.count {
|
||||
// Wrap around to the top if specified
|
||||
return wrapping ? Array<Int>(0..<self.count) : []
|
||||
} else {
|
||||
// Start at the selection and wrap around to the beginning
|
||||
return Array<Int>(startIndex..<self.count) + (wrapping ? Array<Int>(0..<startIndex) : [])
|
||||
}
|
||||
}
|
||||
func rowOfNextUnreadArticle(_ selectedRow: Int, wrappingToTop wrapping: Bool) -> Int? {
|
||||
if isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
var rowIndex = selectedRow
|
||||
while(true) {
|
||||
|
||||
rowIndex = rowIndex + 1
|
||||
if rowIndex >= count {
|
||||
break
|
||||
}
|
||||
for rowIndex in orderedRowIndexes(fromIndex: selectedRow + 1, wrappingToTop: wrapping) {
|
||||
let article = articleAtRow(rowIndex)!
|
||||
if !article.status.read {
|
||||
return rowIndex
|
||||
|
Loading…
x
Reference in New Issue
Block a user