From 644e9da1c0f8209f6a377d2e80acb7dd323428e0 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 17 Jul 2020 20:08:49 -0500 Subject: [PATCH] Implement open in browser timeline context menu item. --- Multiplatform/Shared/SceneModel.swift | 26 ++++++------------ .../Shared/SceneNavigationView.swift | 2 +- .../Shared/Timeline/TimelineContextMenu.swift | 12 +++++++++ .../Shared/Timeline/TimelineModel.swift | 27 ++++++++++++++++++- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/Multiplatform/Shared/SceneModel.swift b/Multiplatform/Shared/SceneModel.swift index 0200e436b..bab636c74 100644 --- a/Multiplatform/Shared/SceneModel.swift +++ b/Multiplatform/Shared/SceneModel.swift @@ -6,11 +6,7 @@ // Copyright © 2020 Ranchero Software. All rights reserved. // -#if os(macOS) -import AppKit -#else -import UIKit -#endif +import Foundation import Combine import Account import Articles @@ -58,28 +54,22 @@ final class SceneModel: ObservableObject { } } - // MARK Navigation API - - func openInBrowser() { - guard let link = selectedArticles.first?.preferredLink else { return } - - #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 - } - // MARK: Article Management API + /// Toggles the read status for the selected articles func toggleReadStatusForSelectedArticles() { timelineModel.toggleReadStatusForSelectedArticles() } + /// Toggles the star status for the selected articles func toggleStarredStatusForSelectedArticles() { timelineModel.toggleStarredStatusForSelectedArticles() } + + /// Opens the selected article in an external browser + func openSelectedArticleInBrowser() { + timelineModel.openSelectedArticleInBrowser() + } /// Retrieves the article before the given article in the Timeline func findPrevArticle(_ article: Article) -> Article? { diff --git a/Multiplatform/Shared/SceneNavigationView.swift b/Multiplatform/Shared/SceneNavigationView.swift index 35cd3b5a7..424fa01ee 100644 --- a/Multiplatform/Shared/SceneNavigationView.swift +++ b/Multiplatform/Shared/SceneNavigationView.swift @@ -158,7 +158,7 @@ struct SceneNavigationView: View { } ToolbarItem { Button { - sceneModel.openInBrowser() + sceneModel.openSelectedArticleInBrowser() } label: { AppAssets.openInBrowserImage } diff --git a/Multiplatform/Shared/Timeline/TimelineContextMenu.swift b/Multiplatform/Shared/Timeline/TimelineContextMenu.swift index 839800b97..98d5949ea 100644 --- a/Multiplatform/Shared/Timeline/TimelineContextMenu.swift +++ b/Multiplatform/Shared/Timeline/TimelineContextMenu.swift @@ -81,5 +81,17 @@ struct TimelineContextMenu: View { } } + if timelineModel.canOpenIndicatedArticleInBrowser(timelineItem.article) { + Divider() + Button { + timelineModel.openIndicatedArticleInBrowser(timelineItem.article) + } label: { + Text("Open in Browser") + #if os(iOS) + AppAssets.openInBrowserImage + #endif + } + } + } } diff --git a/Multiplatform/Shared/Timeline/TimelineModel.swift b/Multiplatform/Shared/Timeline/TimelineModel.swift index 3bbe17553..44f68d9de 100644 --- a/Multiplatform/Shared/Timeline/TimelineModel.swift +++ b/Multiplatform/Shared/Timeline/TimelineModel.swift @@ -6,7 +6,11 @@ // Copyright © 2020 Ranchero Software. All rights reserved. // -import Foundation +#if os(macOS) +import AppKit +#else +import UIKit +#endif import Combine import RSCore import Account @@ -223,6 +227,27 @@ class TimelineModel: ObservableObject, UndoableCommandRunner { func markSelectedArticlesAsUnstarred() { markArticlesWithUndo(selectedArticles, statusKey: .starred, flag: false) } + + func canOpenIndicatedArticleInBrowser(_ article: Article) -> Bool { + guard indicatedArticles(article).count == 1 else { return false } + return article.preferredLink != nil + } + + func openIndicatedArticleInBrowser(_ article: Article) { + guard let link = article.preferredLink else { return } + + #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 + } + + func openSelectedArticleInBrowser() { + guard let article = selectedArticles.first else { return } + openIndicatedArticleInBrowser(article) + } func articleFor(_ articleID: String) -> Article? { return idToArticleDictionary[articleID]