From b77e2164cd936a4a251f36716b2027969cc31ed1 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 27 Jul 2020 15:43:58 -0500 Subject: [PATCH] Revert using combine for toolbar buttons as it was inconsistent with context menus --- Multiplatform/Shared/SceneModel.swift | 8 +- .../Shared/Timeline/TimelineModel.swift | 122 ++++++++---------- 2 files changed, 55 insertions(+), 75 deletions(-) diff --git a/Multiplatform/Shared/SceneModel.swift b/Multiplatform/Shared/SceneModel.swift index 18226be92..f644c391d 100644 --- a/Multiplatform/Shared/SceneModel.swift +++ b/Multiplatform/Shared/SceneModel.swift @@ -61,22 +61,22 @@ final class SceneModel: ObservableObject { /// Marks all the articles in the Timeline as read func markAllAsRead() { - timelineModel.markAllAsReadSubject.send() + timelineModel.markAllAsRead() } /// Toggles the read status for the selected articles func toggleReadStatusForSelectedArticles() { - timelineModel.toggleReadStatusForSelectedArticlesSubject.send() + timelineModel.toggleReadStatusForSelectedArticles() } /// Toggles the star status for the selected articles func toggleStarredStatusForSelectedArticles() { - timelineModel.toggleStarredStatusForSelectedArticlesSubject.send() + timelineModel.toggleStarredStatusForSelectedArticles() } /// Opens the selected article in an external browser func openSelectedArticleInBrowser() { - timelineModel.openSelectedArticlesInBrowserSubject.send() + timelineModel.openSelectedArticleInBrowser() } /// Retrieves the article before the given article in the Timeline diff --git a/Multiplatform/Shared/Timeline/TimelineModel.swift b/Multiplatform/Shared/Timeline/TimelineModel.swift index a94c67323..307137c8e 100644 --- a/Multiplatform/Shared/Timeline/TimelineModel.swift +++ b/Multiplatform/Shared/Timeline/TimelineModel.swift @@ -43,10 +43,6 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { var articlesSubject = ReplaySubject<[Article], Never>(bufferSize: 1) - var markAllAsReadSubject = PassthroughSubject() - var toggleReadStatusForSelectedArticlesSubject = PassthroughSubject() - var toggleStarredStatusForSelectedArticlesSubject = PassthroughSubject() - var openSelectedArticlesInBrowserSubject = PassthroughSubject() var changeReadFilterSubject = PassthroughSubject() var selectNextUnreadSubject = PassthroughSubject() @@ -71,8 +67,6 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { subscribeToArticleFetchChanges() subscribeToArticleSelectionChanges() subscribeToArticleStatusChanges() - subscribeToArticleMarkingEvents() - subscribeToOpenInBrowserEvents() } // MARK: API @@ -120,6 +114,17 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { // TODO: Implement me! } + func toggleReadStatusForSelectedArticles() { + guard !selectedArticles.isEmpty else { + return + } + if selectedArticles.anyArticleIsUnread() { + markSelectedArticlesAsRead() + } else { + markSelectedArticlesAsUnread() + } + } + func canMarkIndicatedArticlesAsRead(_ timelineItem: TimelineItem) -> Bool { let articles = indicatedTimelineItems(timelineItem).map { $0.article } return articles.anyArticleIsUnread() @@ -130,6 +135,10 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { markArticlesWithUndo(articles, statusKey: .read, flag: true) } + func markSelectedArticlesAsRead() { + markArticlesWithUndo(selectedArticles, statusKey: .read, flag: true) + } + func canMarkIndicatedArticlesAsUnread(_ timelineItem: TimelineItem) -> Bool { let articles = indicatedTimelineItems(timelineItem).map { $0.article } return articles.anyArticleIsReadAndCanMarkUnread() @@ -140,6 +149,10 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { markArticlesWithUndo(articles, statusKey: .read, flag: false) } + func markSelectedArticlesAsUnread() { + markArticlesWithUndo(selectedArticles, statusKey: .read, flag: false) + } + func canMarkAboveAsRead(_ timelineItem: TimelineItem) -> Bool { let timelineItem = indicatedAboveTimelineItem(timelineItem) return articles.articlesAbove(position: timelineItem.position).canMarkAllAsRead() @@ -174,6 +187,25 @@ 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 + } + if selectedArticles.anyArticleIsUnstarred() { + markSelectedArticlesAsStarred() + } else { + markSelectedArticlesAsUnstarred() + } + } + func canMarkIndicatedArticlesAsStarred(_ timelineItem: TimelineItem) -> Bool { let articles = indicatedTimelineItems(timelineItem).map { $0.article } return articles.anyArticleIsUnstarred() @@ -184,6 +216,10 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { markArticlesWithUndo(articles, statusKey: .starred, flag: true) } + func markSelectedArticlesAsStarred() { + markArticlesWithUndo(selectedArticles, statusKey: .starred, flag: true) + } + func canMarkIndicatedArticlesAsUnstarred(_ timelineItem: TimelineItem) -> Bool { let articles = indicatedTimelineItems(timelineItem).map { $0.article } return articles.anyArticleIsStarred() @@ -194,11 +230,20 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { markArticlesWithUndo(articles, statusKey: .starred, flag: false) } + func markSelectedArticlesAsUnstarred() { + markArticlesWithUndo(selectedArticles, statusKey: .starred, flag: false) + } + func canOpenIndicatedArticleInBrowser(_ timelineItem: TimelineItem) -> Bool { guard indicatedTimelineItems(timelineItem).count == 1 else { return false } return timelineItem.article.preferredLink != nil } + func openSelectedArticleInBrowser() { + guard let article = selectedArticles.first else { return } + openIndicatedArticleInBrowser(article) + } + func openIndicatedArticleInBrowser(_ timelineItem: TimelineItem) { openIndicatedArticleInBrowser(timelineItem.article) } @@ -440,71 +485,6 @@ private extension TimelineModel { .sink { markArticles(Set([$0]), statusKey: .read, flag: true) } .store(in: &cancellables) } - - func subscribeToArticleMarkingEvents() { - guard let selectedArticlesPublisher = selectedArticlesPublisher else { return } - - let markAllAsReadPublisher = markAllAsReadSubject - .withLatestFrom(articlesSubject) - .filter { !$0.isEmpty } - .map { articles -> ([Article], ArticleStatus.Key, Bool) in - return (articles, ArticleStatus.Key.read, true) - } - - let toggleReadPublisher = toggleReadStatusForSelectedArticlesSubject - .withLatestFrom(selectedArticlesPublisher) - .filter { !$0.isEmpty } - .map { selectedArticles -> ([Article], ArticleStatus.Key, Bool) in - if selectedArticles.anyArticleIsUnread() { - return (selectedArticles, ArticleStatus.Key.read, true) - } else { - return (selectedArticles, ArticleStatus.Key.read, false) - } - } - - let toggleStarred = toggleStarredStatusForSelectedArticlesSubject - .withLatestFrom(selectedArticlesPublisher) - .filter { !$0.isEmpty } - .map { selectedArticles -> ([Article], ArticleStatus.Key, Bool) in - if selectedArticles.anyArticleIsUnstarred() { - return (selectedArticles, ArticleStatus.Key.starred, true) - } else { - return (selectedArticles, ArticleStatus.Key.starred, false) - } - } - - markAllAsReadPublisher - .merge(with: toggleReadPublisher, toggleStarred) - .sink { [weak self] (articles, key, flag) in - if let undoManager = self?.undoManager, - let markReadCommand = MarkStatusCommand(initialArticles: articles, statusKey: key, flag: flag, undoManager: undoManager) { - self?.runCommand(markReadCommand) - } else { - markArticles(Set(articles), statusKey: key, flag: flag) - } - } - .store(in: &cancellables) - - } - - func subscribeToOpenInBrowserEvents() { - guard let selectedArticlesPublisher = selectedArticlesPublisher else { return } - - let selectedArticleOpenInBrowserPublisher = openSelectedArticlesInBrowserSubject - .withLatestFrom(selectedArticlesPublisher) - .compactMap { $0.first?.preferredLink } - - selectedArticleOpenInBrowserPublisher - .sink { link in - #if os(macOS) - Browser.open(link, invertPreference: NSApp.currentEvent?.modifierFlags.contains(.shift) ?? false) - #else - guard let url = URL(string: link) else { return } - UIApplication.shared.open(url, options: [:]) - #endif - } - .store(in: &cancellables) - } // MARK: Article Fetching