Replace Mark Older as Read with Mark Above and Mark Below.
This commit is contained in:
parent
fc447121d6
commit
d94e090094
@ -452,9 +452,15 @@
|
|||||||
<action selector="markAllAsRead:" target="Ady-hI-5gd" id="154-2D-ONk"/>
|
<action selector="markAllAsRead:" target="Ady-hI-5gd" id="154-2D-ONk"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem title="Mark Older as Read" keyEquivalent="K" id="p1o-EG-Uo8">
|
<menuItem title="Mark Above as Read" keyEquivalent="k" id="p1o-EG-Uo8">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="markOlderArticlesAsRead:" target="Ady-hI-5gd" id="gzq-X5-0aC"/>
|
<action selector="markAboveArticlesAsRead:" target="Ady-hI-5gd" id="BJY-oR-uvr"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Mark Below as Read" keyEquivalent="K" id="8lZ-XI-I4y">
|
||||||
|
<connections>
|
||||||
|
<action selector="markBelowArticlesAsRead:" target="Ady-hI-5gd" id="Jnm-LF-mrf"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="gB0-WX-2Gd"/>
|
<menuItem isSeparatorItem="YES" id="gB0-WX-2Gd"/>
|
||||||
|
@ -198,8 +198,12 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
|||||||
return validateToggleStarred(item)
|
return validateToggleStarred(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.action == #selector(markOlderArticlesAsRead(_:)) {
|
if item.action == #selector(markAboveArticlesAsRead(_:)) {
|
||||||
return canMarkOlderArticlesAsRead()
|
return canMarkAboveArticlesAsRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.action == #selector(markBelowArticlesAsRead(_:)) {
|
||||||
|
return canMarkBelowArticlesAsRead()
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.action == #selector(toggleArticleExtractor(_:)) {
|
if item.action == #selector(toggleArticleExtractor(_:)) {
|
||||||
@ -360,8 +364,12 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
|
|||||||
splitViewController!.toggleSidebar(sender)
|
splitViewController!.toggleSidebar(sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func markOlderArticlesAsRead(_ sender: Any?) {
|
@IBAction func markAboveArticlesAsRead(_ sender: Any?) {
|
||||||
currentTimelineViewController?.markOlderArticlesRead()
|
currentTimelineViewController?.markAboveArticlesRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func markBelowArticlesAsRead(_ sender: Any?) {
|
||||||
|
currentTimelineViewController?.markBelowArticlesRead()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func navigateToTimeline(_ sender: Any?) {
|
@IBAction func navigateToTimeline(_ sender: Any?) {
|
||||||
@ -808,9 +816,12 @@ private extension MainWindowController {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func canMarkOlderArticlesAsRead() -> Bool {
|
func canMarkAboveArticlesAsRead() -> Bool {
|
||||||
|
return currentTimelineViewController?.canMarkAboveArticlesAsRead() ?? false
|
||||||
|
}
|
||||||
|
|
||||||
return currentTimelineViewController?.canMarkOlderArticlesAsRead() ?? false
|
func canMarkBelowArticlesAsRead() -> Bool {
|
||||||
|
return currentTimelineViewController?.canMarkBelowArticlesAsRead() ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
func canShowShareMenu() -> Bool {
|
func canShowShareMenu() -> Bool {
|
||||||
|
@ -33,39 +33,31 @@ extension TimelineViewController {
|
|||||||
extension TimelineViewController {
|
extension TimelineViewController {
|
||||||
|
|
||||||
@objc func markArticlesReadFromContextualMenu(_ sender: Any?) {
|
@objc func markArticlesReadFromContextualMenu(_ sender: Any?) {
|
||||||
|
guard let articles = articles(from: sender) else { return }
|
||||||
guard let articles = articles(from: sender) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
markArticles(articles, read: true)
|
markArticles(articles, read: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func markArticlesUnreadFromContextualMenu(_ sender: Any?) {
|
@objc func markArticlesUnreadFromContextualMenu(_ sender: Any?) {
|
||||||
|
guard let articles = articles(from: sender) else { return }
|
||||||
guard let articles = articles(from: sender) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
markArticles(articles, read: false)
|
markArticles(articles, read: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func markOlderArticlesReadFromContextualMenu(_ sender: Any?) {
|
@objc func markAboveArticlesReadFromContextualMenu(_ sender: Any?) {
|
||||||
|
guard let articles = articles(from: sender) else { return }
|
||||||
guard let articles = articles(from: sender) else {
|
markAboveArticlesRead(articles)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
markOlderArticlesRead(articles)
|
|
||||||
|
@objc func markBelowArticlesReadFromContextualMenu(_ sender: Any?) {
|
||||||
|
guard let articles = articles(from: sender) else { return }
|
||||||
|
markBelowArticlesRead(articles)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func markArticlesStarredFromContextualMenu(_ sender: Any?) {
|
@objc func markArticlesStarredFromContextualMenu(_ sender: Any?) {
|
||||||
|
guard let articles = articles(from: sender) else { return }
|
||||||
guard let articles = articles(from: sender) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
markArticles(articles, starred: true)
|
markArticles(articles, starred: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func markArticlesUnstarredFromContextualMenu(_ sender: Any?) {
|
@objc func markArticlesUnstarredFromContextualMenu(_ sender: Any?) {
|
||||||
|
|
||||||
guard let articles = articles(from: sender) else {
|
guard let articles = articles(from: sender) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -111,17 +103,14 @@ extension TimelineViewController {
|
|||||||
private extension TimelineViewController {
|
private extension TimelineViewController {
|
||||||
|
|
||||||
func markArticles(_ articles: [Article], read: Bool) {
|
func markArticles(_ articles: [Article], read: Bool) {
|
||||||
|
|
||||||
markArticles(articles, statusKey: .read, flag: read)
|
markArticles(articles, statusKey: .read, flag: read)
|
||||||
}
|
}
|
||||||
|
|
||||||
func markArticles(_ articles: [Article], starred: Bool) {
|
func markArticles(_ articles: [Article], starred: Bool) {
|
||||||
|
|
||||||
markArticles(articles, statusKey: .starred, flag: starred)
|
markArticles(articles, statusKey: .starred, flag: starred)
|
||||||
}
|
}
|
||||||
|
|
||||||
func markArticles(_ articles: [Article], statusKey: ArticleStatus.Key, flag: Bool) {
|
func markArticles(_ articles: [Article], statusKey: ArticleStatus.Key, flag: Bool) {
|
||||||
|
|
||||||
guard let undoManager = undoManager, let markStatusCommand = MarkStatusCommand(initialArticles: articles, statusKey: statusKey, flag: flag, undoManager: undoManager) else {
|
guard let undoManager = undoManager, let markStatusCommand = MarkStatusCommand(initialArticles: articles, statusKey: statusKey, flag: flag, undoManager: undoManager) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -130,24 +119,20 @@ private extension TimelineViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unreadArticles(from articles: [Article]) -> [Article]? {
|
func unreadArticles(from articles: [Article]) -> [Article]? {
|
||||||
|
|
||||||
let filteredArticles = articles.filter { !$0.status.read }
|
let filteredArticles = articles.filter { !$0.status.read }
|
||||||
return filteredArticles.isEmpty ? nil : filteredArticles
|
return filteredArticles.isEmpty ? nil : filteredArticles
|
||||||
}
|
}
|
||||||
|
|
||||||
func readArticles(from articles: [Article]) -> [Article]? {
|
func readArticles(from articles: [Article]) -> [Article]? {
|
||||||
|
|
||||||
let filteredArticles = articles.filter { $0.status.read }
|
let filteredArticles = articles.filter { $0.status.read }
|
||||||
return filteredArticles.isEmpty ? nil : filteredArticles
|
return filteredArticles.isEmpty ? nil : filteredArticles
|
||||||
}
|
}
|
||||||
|
|
||||||
func articles(from sender: Any?) -> [Article]? {
|
func articles(from sender: Any?) -> [Article]? {
|
||||||
|
|
||||||
return (sender as? NSMenuItem)?.representedObject as? [Article]
|
return (sender as? NSMenuItem)?.representedObject as? [Article]
|
||||||
}
|
}
|
||||||
|
|
||||||
func menu(for articles: [Article]) -> NSMenu? {
|
func menu(for articles: [Article]) -> NSMenu? {
|
||||||
|
|
||||||
let menu = NSMenu(title: "")
|
let menu = NSMenu(title: "")
|
||||||
|
|
||||||
if articles.anyArticleIsUnread() {
|
if articles.anyArticleIsUnread() {
|
||||||
@ -162,8 +147,11 @@ private extension TimelineViewController {
|
|||||||
if articles.anyArticleIsStarred() {
|
if articles.anyArticleIsStarred() {
|
||||||
menu.addItem(markUnstarredMenuItem(articles))
|
menu.addItem(markUnstarredMenuItem(articles))
|
||||||
}
|
}
|
||||||
if articles.count > 0 {
|
if let first = articles.first, self.articles.articlesAbove(article: first).canMarkAllAsRead() {
|
||||||
menu.addItem(markOlderReadMenuItem(articles))
|
menu.addItem(markAboveReadMenuItem(articles))
|
||||||
|
}
|
||||||
|
if let last = articles.last, self.articles.articlesBelow(article: last).canMarkAllAsRead() {
|
||||||
|
menu.addItem(markBelowReadMenuItem(articles))
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.addSeparatorIfNeeded()
|
menu.addSeparatorIfNeeded()
|
||||||
@ -239,8 +227,12 @@ private extension TimelineViewController {
|
|||||||
return menuItem(NSLocalizedString("Mark as Unstarred", comment: "Command"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles)
|
return menuItem(NSLocalizedString("Mark as Unstarred", comment: "Command"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles)
|
||||||
}
|
}
|
||||||
|
|
||||||
func markOlderReadMenuItem(_ articles: [Article]) -> NSMenuItem {
|
func markAboveReadMenuItem(_ articles: [Article]) -> NSMenuItem {
|
||||||
return menuItem(NSLocalizedString("Mark Older as Read", comment: "Command"), #selector(markOlderArticlesReadFromContextualMenu(_:)), articles)
|
return menuItem(NSLocalizedString("Mark Above as Read", comment: "Command"), #selector(markAboveArticlesReadFromContextualMenu(_:)), articles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func markBelowReadMenuItem(_ articles: [Article]) -> NSMenuItem {
|
||||||
|
return menuItem(NSLocalizedString("Mark Below as Read", comment: "Command"), #selector(markBelowArticlesReadFromContextualMenu(_:)), articles)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectFeedInSidebarMenuItem(_ feed: WebFeed) -> NSMenuItem {
|
func selectFeedInSidebarMenuItem(_ feed: WebFeed) -> NSMenuItem {
|
||||||
|
@ -435,35 +435,38 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||||||
return .canDoNothing
|
return .canDoNothing
|
||||||
}
|
}
|
||||||
|
|
||||||
func markOlderArticlesRead() {
|
func markAboveArticlesRead() {
|
||||||
markOlderArticlesRead(selectedArticles)
|
markAboveArticlesRead(selectedArticles)
|
||||||
}
|
}
|
||||||
|
|
||||||
func canMarkOlderArticlesAsRead() -> Bool {
|
func markBelowArticlesRead() {
|
||||||
return !selectedArticles.isEmpty
|
markBelowArticlesRead(selectedArticles)
|
||||||
}
|
}
|
||||||
|
|
||||||
func markOlderArticlesRead(_ selectedArticles: [Article]) {
|
func canMarkAboveArticlesAsRead() -> Bool {
|
||||||
// Mark articles older than the selectedArticles(s) as read.
|
guard let first = selectedArticles.first else { return false }
|
||||||
|
return articles.articlesAbove(article: first).canMarkAllAsRead()
|
||||||
|
}
|
||||||
|
|
||||||
var cutoffDate: Date? = nil
|
func canMarkBelowArticlesAsRead() -> Bool {
|
||||||
for article in selectedArticles {
|
guard let last = selectedArticles.last else { return false }
|
||||||
if cutoffDate == nil {
|
return articles.articlesBelow(article: last).canMarkAllAsRead()
|
||||||
cutoffDate = article.logicalDatePublished
|
|
||||||
}
|
}
|
||||||
else if cutoffDate! > article.logicalDatePublished {
|
|
||||||
cutoffDate = article.logicalDatePublished
|
func markAboveArticlesRead(_ selectedArticles: [Article]) {
|
||||||
}
|
guard let first = selectedArticles.first else { return }
|
||||||
}
|
let articlesToMark = articles.articlesAbove(article: first)
|
||||||
if cutoffDate == nil {
|
guard !articlesToMark.isEmpty else { return }
|
||||||
|
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMark, markingRead: true, undoManager: undoManager) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
runCommand(markReadCommand)
|
||||||
let articlesToMark = articles.filter { $0.logicalDatePublished < cutoffDate! }
|
|
||||||
if articlesToMark.isEmpty {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func markBelowArticlesRead(_ selectedArticles: [Article]) {
|
||||||
|
guard let last = selectedArticles.last else { return }
|
||||||
|
let articlesToMark = articles.articlesBelow(article: last)
|
||||||
|
guard !articlesToMark.isEmpty else { return }
|
||||||
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMark, markingRead: true, undoManager: undoManager) else {
|
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMark, markingRead: true, undoManager: undoManager) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user