Add marking starred and read context menu items to Timeline

This commit is contained in:
Maurice Parker 2020-07-17 19:46:05 -05:00
parent 538d886bf4
commit a102b9f63d
2 changed files with 129 additions and 48 deletions

View File

@ -15,6 +15,50 @@ struct TimelineContextMenu: View {
@ViewBuilder var body: some View {
if timelineModel.canMarkIndicatedArticlesAsRead(timelineItem.article) {
Button {
timelineModel.markIndicatedArticlesAsRead(timelineItem.article)
} label: {
Text("Mark as Read")
#if os(iOS)
AppAssets.readOpenImage
#endif
}
}
if timelineModel.canMarkIndicatedArticlesAsUnread(timelineItem.article) {
Button {
timelineModel.markIndicatedArticlesAsUnread(timelineItem.article)
} label: {
Text("Mark as Unread")
#if os(iOS)
AppAssets.readClosedImage
#endif
}
}
if timelineModel.canMarkIndicatedArticlesAsStarred(timelineItem.article) {
Button {
timelineModel.markIndicatedArticlesAsStarred(timelineItem.article)
} label: {
Text("Mark as Starred")
#if os(iOS)
AppAssets.starClosedImage
#endif
}
}
if timelineModel.canMarkIndicatedArticlesAsUnstarred(timelineItem.article) {
Button {
timelineModel.markIndicatedArticlesAsUnstarred(timelineItem.article)
} label: {
Text("Mark as Unstarred")
#if os(iOS)
AppAssets.starOpenImage
#endif
}
}
if timelineModel.canMarkAboveAsRead(timelineItem.article) {
Button {
timelineModel.markAboveAsRead(timelineItem.article)

View File

@ -133,18 +133,56 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
}
}
func markSelectedArticlesAsRead() {
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingRead: true, undoManager: undoManager) else {
return
func canMarkIndicatedArticlesAsRead(_ article: Article) -> Bool {
let articles = indicatedArticles(article)
return articles.anyArticleIsUnread()
}
runCommand(markReadCommand)
func markIndicatedArticlesAsRead(_ article: Article) {
let articles = indicatedArticles(article)
markArticlesWithUndo(articles, statusKey: .read, flag: true)
}
func markSelectedArticlesAsRead() {
markArticlesWithUndo(selectedArticles, statusKey: .read, flag: true)
}
func canMarkIndicatedArticlesAsUnread(_ article: Article) -> Bool {
let articles = indicatedArticles(article)
return articles.anyArticleIsReadAndCanMarkUnread()
}
func markIndicatedArticlesAsUnread(_ article: Article) {
let articles = indicatedArticles(article)
markArticlesWithUndo(articles, statusKey: .read, flag: false)
}
func markSelectedArticlesAsUnread() {
guard let undoManager = undoManager, let markUnreadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingRead: false, undoManager: undoManager) else {
return
markArticlesWithUndo(selectedArticles, statusKey: .read, flag: false)
}
runCommand(markUnreadCommand)
func canMarkAboveAsRead(_ article: Article) -> Bool {
let article = indicatedAboveArticle(article)
return articles.articlesAbove(article: article).canMarkAllAsRead()
}
func markAboveAsRead(_ article: Article) {
let article = indicatedAboveArticle(article)
let articlesToMark = articles.articlesAbove(article: article)
guard !articlesToMark.isEmpty else { return }
markArticlesWithUndo(articlesToMark, statusKey: .read, flag: true)
}
func canMarkBelowAsRead(_ article: Article) -> Bool {
let article = indicatedBelowArticle(article)
return articles.articlesBelow(article: article).canMarkAllAsRead()
}
func markBelowAsRead(_ article: Article) {
let article = indicatedBelowArticle(article)
let articlesToMark = articles.articlesBelow(article: article)
guard !articlesToMark.isEmpty else { return }
markArticlesWithUndo(articlesToMark, statusKey: .read, flag: true)
}
func toggleStarredStatusForSelectedArticles() {
@ -158,48 +196,32 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
}
}
func markSelectedArticlesAsStarred() {
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingStarred: true, undoManager: undoManager) else {
return
func canMarkIndicatedArticlesAsStarred(_ article: Article) -> Bool {
let articles = indicatedArticles(article)
return articles.anyArticleIsUnstarred()
}
runCommand(markReadCommand)
func markIndicatedArticlesAsStarred(_ article: Article) {
let articles = indicatedArticles(article)
markArticlesWithUndo(articles, statusKey: .starred, flag: true)
}
func markSelectedArticlesAsStarred() {
markArticlesWithUndo(selectedArticles, statusKey: .starred, flag: true)
}
func canMarkIndicatedArticlesAsUnstarred(_ article: Article) -> Bool {
let articles = indicatedArticles(article)
return articles.anyArticleIsStarred()
}
func markIndicatedArticlesAsUnstarred(_ article: Article) {
let articles = indicatedArticles(article)
markArticlesWithUndo(articles, statusKey: .starred, flag: false)
}
func markSelectedArticlesAsUnstarred() {
guard let undoManager = undoManager, let markUnreadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingStarred: false, undoManager: undoManager) else {
return
}
runCommand(markUnreadCommand)
}
func canMarkAboveAsRead(_ article: Article) -> Bool {
let article = correctedAboveArticle(article)
return articles.articlesAbove(article: article).canMarkAllAsRead()
}
func canMarkBelowAsRead(_ article: Article) -> Bool {
let article = correctedBelowArticle(article)
return articles.articlesBelow(article: article).canMarkAllAsRead()
}
func markAboveAsRead(_ article: Article) {
let article = correctedAboveArticle(article)
let articlesToMark = articles.articlesAbove(article: article)
guard !articlesToMark.isEmpty else { return }
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMark, markingRead: true, undoManager: undoManager) else {
return
}
runCommand(markReadCommand)
}
func markBelowAsRead(_ article: Article) {
let article = correctedBelowArticle(article)
let articlesToMark = articles.articlesBelow(article: article)
guard !articlesToMark.isEmpty else { return }
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMark, markingRead: true, undoManager: undoManager) else {
return
}
runCommand(markReadCommand)
markArticlesWithUndo(selectedArticles, statusKey: .starred, flag: false)
}
func articleFor(_ articleID: String) -> Article? {
@ -230,7 +252,15 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
private extension TimelineModel {
func correctedAboveArticle(_ article: Article) -> Article {
func indicatedArticles(_ article: Article) -> [Article] {
if selectedArticles.contains(article) {
return selectedArticles
} else {
return [article]
}
}
func indicatedAboveArticle(_ article: Article) -> Article {
if selectedArticles.contains(article) {
return selectedArticles.first!
} else {
@ -238,7 +268,7 @@ private extension TimelineModel {
}
}
func correctedBelowArticle(_ article: Article) -> Article {
func indicatedBelowArticle(_ article: Article) -> Article {
if selectedArticles.contains(article) {
return selectedArticles.last!
} else {
@ -246,6 +276,13 @@ private extension TimelineModel {
}
}
func markArticlesWithUndo(_ articles: [Article], statusKey: ArticleStatus.Key, flag: Bool) {
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articles, statusKey: statusKey, flag: flag, undoManager: undoManager) else {
return
}
runCommand(markReadCommand)
}
// MARK: Notifications
@objc func statusesDidChange(_ note: Notification) {