Implement the Mark All as Read button
This commit is contained in:
parent
40e0a1b676
commit
e391b29353
@ -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 {
|
||||
|
@ -92,6 +92,7 @@ struct SceneNavigationView: View {
|
||||
}
|
||||
ToolbarItem {
|
||||
Button {
|
||||
sceneModel.markAllAsRead()
|
||||
} label: {
|
||||
AppAssets.markAllAsReadImagePDF
|
||||
.resizable()
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user