Enabled toolbar buttons for read and star

This commit is contained in:
Maurice Parker 2020-07-11 19:52:28 -05:00
parent 92ac91d9d5
commit 7998b5450b
4 changed files with 85 additions and 13 deletions

@ -33,7 +33,7 @@ struct ArticleToolbarModifier: ViewModifier {
}
ToolbarItem(placement: .bottomBar) {
Button(action: { }, label: {
Button(action: { sceneModel.toggleReadStatusForSelectedArticles() }, label: {
if sceneModel.readButtonState == .on {
AppAssets.readClosedImage
} else {
@ -49,7 +49,7 @@ struct ArticleToolbarModifier: ViewModifier {
}
ToolbarItem(placement: .bottomBar) {
Button(action: { }, label: {
Button(action: { sceneModel.toggleStarredStatusForSelectedArticles() }, label: {
if sceneModel.starButtonState == .on {
AppAssets.starClosedImage
} else {

@ -7,6 +7,7 @@
//
import Foundation
import Combine
import Account
import Articles
import RSCore
@ -25,6 +26,8 @@ final class SceneModel: ObservableObject {
private(set) var sidebarModel = SidebarModel()
private(set) var timelineModel = TimelineModel()
private var selectedArticlesCancellable: AnyCancellable?
// MARK: Initialization API
/// Prepares the SceneModel to be used in the views
@ -39,10 +42,22 @@ final class SceneModel: ObservableObject {
self.webViewProvider = WebViewProvider(articleIconSchemeHandler: self.articleIconSchemeHandler!)
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
selectedArticlesCancellable = timelineModel.$selectedArticles.sink { [weak self] articles in
self?.updateArticleState(articles: articles)
}
}
// MARK: Article Management API
func toggleReadStatusForSelectedArticles() {
timelineModel.toggleReadStatusForSelectedArticles()
}
func toggleStarredStatusForSelectedArticles() {
timelineModel.toggleStarredStatusForSelectedArticles()
}
/// Retrieves the article before the given article in the Timeline
func findPrevArticle(_ article: Article) -> Article? {
return timelineModel.findPrevArticle(article)
@ -92,15 +107,13 @@ private extension SceneModel {
}
let selectedArticleIDs = timelineModel.selectedArticles.map { $0.articleID }
if !articleIDs.intersection(selectedArticleIDs).isEmpty {
updateArticleState()
updateArticleState(articles: timelineModel.selectedArticles)
}
}
// MARK: Button State Updates
func updateArticleState() {
let articles = timelineModel.selectedArticles
func updateArticleState(articles: [Article]) {
guard !articles.isEmpty else {
readButtonState = nil
starButtonState = nil
@ -116,9 +129,9 @@ private extension SceneModel {
}
if articles.anyArticleIsUnstarred() {
starButtonState = .on
} else {
starButtonState = .off
} else {
starButtonState = .on
}
}

@ -98,7 +98,7 @@ struct SceneNavigationView: View {
}).help("Go to Next Unread").padding(.trailing, 40)
}
ToolbarItem {
Button(action: { }, label: {
Button(action: { sceneModel.toggleReadStatusForSelectedArticles() }, label: {
if sceneModel.readButtonState == .on {
AppAssets.readClosedImage
} else {
@ -109,7 +109,7 @@ struct SceneNavigationView: View {
.help(sceneModel.readButtonState == .on ? "Mark as Unread" : "Mark as Read")
}
ToolbarItem {
Button(action: { }, label: {
Button(action: { sceneModel.toggleStarredStatusForSelectedArticles() }, label: {
if sceneModel.starButtonState == .on {
AppAssets.starClosedImage
} else {

@ -31,6 +31,7 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
private var selectedArticleIDsCancellable: AnyCancellable?
private var selectedArticleIDCancellable: AnyCancellable?
private var selectedArticlesCancellable: AnyCancellable?
private var fetchSerialNumber = 0
private let fetchRequestQueue = FetchRequestQueue()
@ -84,6 +85,16 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
self.selectedArticles = [article]
}
}
// TODO: This should be rewritten to use Combine correctly
selectedArticlesCancellable = $selectedArticles.sink { articles in
if articles.count == 1 {
let article = articles.first!
if !article.status.read {
markArticles(Set([article]), statusKey: .read, flag: true)
}
}
}
}
// MARK: API
@ -97,6 +108,56 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
fetchAndReplaceArticlesAsync(feeds: feeds)
}
func toggleReadStatusForSelectedArticles() {
guard !selectedArticles.isEmpty else {
return
}
if selectedArticles.anyArticleIsUnread() {
markSelectedArticlesAsRead()
} else {
markSelectedArticlesAsUnread()
}
}
func markSelectedArticlesAsRead() {
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingRead: true, undoManager: undoManager) else {
return
}
runCommand(markReadCommand)
}
func markSelectedArticlesAsUnread() {
guard let undoManager = undoManager, let markUnreadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingRead: false, undoManager: undoManager) else {
return
}
runCommand(markUnreadCommand)
}
func toggleStarredStatusForSelectedArticles() {
guard !selectedArticles.isEmpty else {
return
}
if selectedArticles.anyArticleIsUnstarred() {
markSelectedArticlesAsStarred()
} else {
markSelectedArticlesAsUnstarred()
}
}
func markSelectedArticlesAsStarred() {
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingStarred: true, undoManager: undoManager) else {
return
}
runCommand(markReadCommand)
}
func markSelectedArticlesAsUnstarred() {
guard let undoManager = undoManager, let markUnreadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingStarred: false, undoManager: undoManager) else {
return
}
runCommand(markUnreadCommand)
}
func articleFor(_ articleID: String) -> Article? {
return idToArticleDictionary[articleID]
}
@ -138,7 +199,7 @@ private extension TimelineModel {
}
}
// MARK:
// MARK: Timeline Management
func sortParametersDidChange() {
performBlockAndRestoreSelection {
@ -202,6 +263,4 @@ private extension TimelineModel {
// TODO: Update unread counts and other item done in didSet on AppKit
}
// MARK: - Notifications
}