Add basic ExtensionPoint support.

This commit is contained in:
Maurice Parker
2020-04-07 15:25:33 -05:00
parent f8667be32b
commit 49cff8eb8e
29 changed files with 299 additions and 140 deletions

View File

@@ -0,0 +1,20 @@
//
// ExtensionPoint.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import RSCore
protocol ExtensionPoint {
/// The title of the command.
var title: String { get }
/// The template image for the command.
var templateImage: RSImage { get }
}

View File

@@ -0,0 +1,49 @@
//
// ExtensionPointManager.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import FeedProvider
import RSCore
struct ExtensionPointManager {
static let shared = ExtensionPointManager()
let marsEdit = SendToMarsEditCommand()
let microblog = SendToMicroBlogCommand()
let twitter = TwitterFeedProvider()
let availableExtensionPoints: [ExtensionPoint]
let activeSendToCommands: [SendToCommand]
let activeFeedProviders: [FeedProvider]
init() {
#if os(macOS)
#if DEBUG
availableExtensionPoints = [marsEdit, microblog, twitter]
activeSendToCommands = [marsEdit, microblog]
activeFeedProviders = [twitter]
#else
availableExtensionPoints = [marsEdit, microblog, twitter]
activeSendToCommands = [marsEdit, microblog]
activeFeedProviders = [twitter]
#endif
#else
#if DEBUG
availableExtensionPoints = [twitter]
activeSendToCommands = []()
activeFeedProviders = [twitter]
#else
availableExtensionPoints = [twitter]
activeSendToCommands = []()
activeFeedProviders = [twitter]
#endif
#endif
}
}

View File

@@ -0,0 +1,14 @@
//
// ExtensionPointType.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
enum ExtensionPoint: Int, Codable {
case sentToCommand = 1
case feedProvider = 2
}

View File

@@ -0,0 +1,84 @@
//
// SendToMarsEditCommand.swift
// NetNewsWire
//
// Created by Brent Simmons on 1/8/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import AppKit
import RSCore
import Articles
final class SendToMarsEditCommand: ExtensionPoint, SendToCommand {
let title = NSLocalizedString("MarsEdit", comment: "MarsEdit")
let templateImage = AppAssets.extensionPointMarsEdit
var image: NSImage? {
return appToUse()?.icon ?? nil
}
private let marsEditApps = [UserApp(bundleID: "com.red-sweater.marsedit4"), UserApp(bundleID: "com.red-sweater.marsedit")]
func canSendObject(_ object: Any?, selectedText: String?) -> Bool {
if let _ = appToUse() {
return true
}
return false
}
func sendObject(_ object: Any?, selectedText: String?) {
guard canSendObject(object, selectedText: selectedText) else {
return
}
guard let article = (object as? ArticlePasteboardWriter)?.article else {
return
}
guard let app = appToUse(), app.launchIfNeeded(), app.bringToFront() else {
return
}
send(article, to: app)
}
}
private extension SendToMarsEditCommand {
func send(_ article: Article, to app: UserApp) {
// App has already been launched.
guard let targetDescriptor = app.targetDescriptor() else {
return
}
let body = article.contentHTML ?? article.contentText ?? article.summary
let authorName = article.authors?.first?.name
let sender = SendToBlogEditorApp(targetDescriptor: targetDescriptor, title: article.title, body: body, summary: article.summary, link: article.externalURL, permalink: article.url, subject: nil, creator: authorName, commentsURL: nil, guid: article.uniqueID, sourceName: article.webFeed?.nameForDisplay, sourceHomeURL: article.webFeed?.homePageURL, sourceFeedURL: article.webFeed?.url)
let _ = sender.send()
}
func appToUse() -> UserApp? {
marsEditApps.forEach{ $0.updateStatus() }
for app in marsEditApps {
if app.isRunning {
return app
}
}
for app in marsEditApps {
if app.existsOnDisk {
return app
}
}
return nil
}
}

View File

@@ -0,0 +1,97 @@
//
// SendToMicroBlogCommand.swift
// NetNewsWire
//
// Created by Brent Simmons on 1/8/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import AppKit
import Articles
import RSCore
// Not undoable.
final class SendToMicroBlogCommand: ExtensionPoint, SendToCommand {
let title = NSLocalizedString("Micro.blog", comment: "Micro.blog")
let templateImage = AppAssets.extensionPointMicroblog
var image: NSImage? {
return microBlogApp.icon
}
private let microBlogApp = UserApp(bundleID: "blog.micro.mac")
func canSendObject(_ object: Any?, selectedText: String?) -> Bool {
microBlogApp.updateStatus()
guard microBlogApp.existsOnDisk, let article = (object as? ArticlePasteboardWriter)?.article, let _ = article.preferredLink else {
return false
}
return true
}
func sendObject(_ object: Any?, selectedText: String?) {
guard canSendObject(object, selectedText: selectedText) else {
return
}
guard let article = (object as? ArticlePasteboardWriter)?.article else {
return
}
guard microBlogApp.launchIfNeeded(), microBlogApp.bringToFront() else {
return
}
// TODO: get text from contentHTML or contentText if no title and no selectedText.
// TODO: consider selectedText.
let s = article.attributionString + article.linkString
let urlQueryDictionary = ["text": s]
guard let urlQueryString = urlQueryDictionary.urlQueryString else {
return
}
guard let url = URL(string: "microblog://post?" + urlQueryString) else {
return
}
let _ = try? NSWorkspace.shared.open(url, options: [], configuration: [:])
}
}
private extension Article {
var attributionString: String {
// Feed name, or feed name + author name (if author is specified per-article).
// Includes trailing space.
if let feedName = webFeed?.nameForDisplay, let authorName = authors?.first?.name {
return feedName + ", " + authorName + ": "
}
if let feedName = webFeed?.nameForDisplay {
return feedName + ": "
}
return ""
}
var linkString: String {
// Title + link or just title (if no link) or just link if no title
if let title = title, let link = preferredLink {
return "[" + title + "](" + link + ")"
}
if let preferredLink = preferredLink {
return preferredLink
}
if let title = title {
return title
}
return ""
}
}

View File

@@ -0,0 +1,23 @@
//
// TwitterFeedProvider+Extensions.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import FeedProvider
import RSCore
extension TwitterFeedProvider: ExtensionPoint {
var title: String {
return NSLocalizedString("Twitter", comment: "Twitter")
}
var templateImage: RSImage {
return AppAssets.extensionPointTwitter
}
}