Implement the Mark All as Read button

This commit is contained in:
Maurice Parker 2020-07-18 04:58:46 -05:00
parent 40e0a1b676
commit e391b29353
4 changed files with 46 additions and 15 deletions

View File

@ -35,6 +35,7 @@ final class SceneModel: ObservableObject {
private(set) var sidebarModel = SidebarModel()
private(set) var timelineModel = TimelineModel()
private var articlesCancellable: AnyCancellable?
private var selectedArticlesCancellable: AnyCancellable?
// MARK: Initialization API
@ -50,13 +51,22 @@ final class SceneModel: ObservableObject {
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
articlesCancellable = timelineModel.$articles.sink { [weak self] articles in
self?.updateMarkAllAsReadButtonsState(articles: articles)
}
selectedArticlesCancellable = timelineModel.$selectedArticles.sink { [weak self] articles in
self?.updateArticleButtonsState(articles: articles)
self?.updateArticleButtonsState(selectedArticles: articles)
}
}
// MARK: Article Management API
/// Marks all the articles in the Timeline as read
func markAllAsRead() {
timelineModel.markAllAsRead()
}
/// Toggles the read status for the selected articles
func toggleReadStatusForSelectedArticles() {
timelineModel.toggleReadStatusForSelectedArticles()
@ -123,16 +133,25 @@ private extension SceneModel {
guard let articleIDs = note.userInfo?[Account.UserInfoKey.articleIDs] as? Set<String> else {
return
}
updateMarkAllAsReadButtonsState(articles: timelineModel.articles)
let selectedArticleIDs = timelineModel.selectedArticles.map { $0.articleID }
if !articleIDs.intersection(selectedArticleIDs).isEmpty {
updateArticleButtonsState(articles: timelineModel.selectedArticles)
updateArticleButtonsState(selectedArticles: timelineModel.selectedArticles)
}
}
// MARK: Button State Updates
func updateArticleButtonsState(articles: [Article]) {
guard !articles.isEmpty else {
func updateMarkAllAsReadButtonsState(articles: [Article]) {
if articles.canMarkAllAsRead() {
markAllAsReadButtonState = false
} else {
markAllAsReadButtonState = nil
}
}
func updateArticleButtonsState(selectedArticles: [Article]) {
guard !selectedArticles.isEmpty else {
readButtonState = nil
starButtonState = nil
openInBrowserButtonState = nil
@ -140,21 +159,21 @@ private extension SceneModel {
return
}
if articles.anyArticleIsUnread() {
if selectedArticles.anyArticleIsUnread() {
readButtonState = true
} else if articles.anyArticleIsReadAndCanMarkUnread() {
} else if selectedArticles.anyArticleIsReadAndCanMarkUnread() {
readButtonState = false
} else {
readButtonState = nil
}
if articles.anyArticleIsUnstarred() {
if selectedArticles.anyArticleIsUnstarred() {
starButtonState = false
} else {
starButtonState = true
}
if articles.count == 1, articles.first?.preferredLink != nil {
if selectedArticles.count == 1, selectedArticles.first?.preferredLink != nil {
openInBrowserButtonState = true
shareButtonState = true
} else {

View File

@ -92,6 +92,7 @@ struct SceneNavigationView: View {
}
ToolbarItem {
Button {
sceneModel.markAllAsRead()
} label: {
AppAssets.markAllAsReadImagePDF
.resizable()

View File

@ -33,6 +33,12 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
@Published var readFilterEnabledTable = [FeedIdentifier: Bool]()
@Published var isReadFiltered: Bool? = nil
@Published var articles = [Article]() {
didSet {
articleDictionaryNeedsUpdate = true
}
}
var undoManager: UndoManager?
var undoableCommands = [UndoableCommand]()
@ -45,13 +51,7 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
private var fetchSerialNumber = 0
private let fetchRequestQueue = FetchRequestQueue()
private var exceptionArticleFetcher: ArticleFetcher?
private var articles = [Article]() {
didSet {
articleDictionaryNeedsUpdate = true
}
}
private var articleDictionaryNeedsUpdate = true
private var _idToArticleDictionary = [String: Article]()
private var idToArticleDictionary: [String: Article] {
@ -198,6 +198,14 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
markArticlesWithUndo(articlesToMark, statusKey: .read, flag: true)
}
func canMarkAllAsRead() -> Bool {
return articles.canMarkAllAsRead()
}
func markAllAsRead() {
markArticlesWithUndo(articles, statusKey: .read, flag: true)
}
func toggleStarredStatusForSelectedArticles() {
guard !selectedArticles.isEmpty else {
return

View File

@ -10,6 +10,7 @@ import SwiftUI
struct TimelineToolbarModifier: ViewModifier {
@EnvironmentObject private var sceneModel: SceneModel
@EnvironmentObject private var timelineModel: TimelineModel
func body(content: Content) -> some View {
@ -34,9 +35,11 @@ struct TimelineToolbarModifier: ViewModifier {
ToolbarItem {
Button {
sceneModel.markAllAsRead()
} label: {
AppAssets.markAllAsReadImage
}
.disabled(sceneModel.markAllAsReadButtonState == nil)
.help("Mark All As Read")
}