From 61b755486aae5a6e934db4d3f95461874842d11d Mon Sep 17 00:00:00 2001
From: Maurice Parker <mo@vincode.io>
Date: Wed, 8 Apr 2020 13:46:15 -0500
Subject: [PATCH] Flesh out the ExtensionPointManager a little

---
 Mac/AppDefaults.swift                         | 10 ++++
 .../SharingServicePickerDelegate.swift        |  9 +--
 Shared/ExtensionPoints/ExtensionPoint.swift   | 47 +++++++++++++++-
 .../ExtensionPointManager.swift               | 55 +++++++++++++++++--
 4 files changed, 109 insertions(+), 12 deletions(-)

diff --git a/Mac/AppDefaults.swift b/Mac/AppDefaults.swift
index 89d42b928..f7e362c68 100644
--- a/Mac/AppDefaults.swift
+++ b/Mac/AppDefaults.swift
@@ -19,6 +19,7 @@ struct AppDefaults {
 	struct Key {
 		static let firstRunDate = "firstRunDate"
 		static let windowState = "windowState"
+		static let activeExtensionPointIDs = "activeExtensionPointIDs"
 		static let lastImageCacheFlushDate = "lastImageCacheFlushDate"
 		static let sidebarFontSize = "sidebarFontSize"
 		static let timelineFontSize = "timelineFontSize"
@@ -72,6 +73,15 @@ struct AppDefaults {
 		}
 	}
 	
+	static var activeExtensionPointIDs: [[AnyHashable : AnyHashable]]? {
+		get {
+			return UserDefaults.standard.object(forKey: Key.activeExtensionPointIDs) as? [[AnyHashable : AnyHashable]]
+		}
+		set {
+			UserDefaults.standard.set(newValue, forKey: Key.activeExtensionPointIDs)
+		}
+	}
+	
 	static var lastImageCacheFlushDate: Date? {
 		get {
 			return date(for: Key.lastImageCacheFlushDate)
diff --git a/Mac/MainWindow/SharingServicePickerDelegate.swift b/Mac/MainWindow/SharingServicePickerDelegate.swift
index 45cbd9eb7..1a5349a42 100644
--- a/Mac/MainWindow/SharingServicePickerDelegate.swift
+++ b/Mac/MainWindow/SharingServicePickerDelegate.swift
@@ -18,25 +18,20 @@ import RSCore
 	}
 	
 	func sharingServicePicker(_ sharingServicePicker: NSSharingServicePicker, sharingServicesForItems items: [Any], proposedSharingServices proposedServices: [NSSharingService]) -> [NSSharingService] {
-
 		return proposedServices + SharingServicePickerDelegate.customSharingServices(for: items)
-		
 	}
 
 	func sharingServicePicker(_ sharingServicePicker: NSSharingServicePicker, delegateFor sharingService: NSSharingService) -> NSSharingServiceDelegate? {
 		return sharingServiceDelegate
 	}
 
-	private static let sendToCommands: [SendToCommand] = {
-		return [SendToMicroBlogCommand(), SendToMarsEditCommand()]
-	}()
-
 	static func customSharingServices(for items: [Any]) -> [NSSharingService] {
-		let customServices = sendToCommands.compactMap { (sendToCommand) -> NSSharingService? in
+		let customServices = ExtensionPointManager.shared.activeSendToCommands.compactMap { (sendToCommand) -> NSSharingService? in
 
 			guard let object = items.first else {
 				return nil
 			}
+			
 			guard sendToCommand.canSendObject(object, selectedText: nil) else {
 				return nil
 			}
diff --git a/Shared/ExtensionPoints/ExtensionPoint.swift b/Shared/ExtensionPoints/ExtensionPoint.swift
index fe5440141..f41e68fe6 100644
--- a/Shared/ExtensionPoints/ExtensionPoint.swift
+++ b/Shared/ExtensionPoints/ExtensionPoint.swift
@@ -39,7 +39,7 @@ enum ExtensionPointType {
 
 }
 
-enum ExtensionPointIdentifer {
+enum ExtensionPointIdentifer: Hashable {
 	case marsEdit
 	case microblog
 	case twitter(String)
@@ -55,6 +55,51 @@ enum ExtensionPointIdentifer {
 		}
 	}
 	
+	public var userInfo: [AnyHashable: AnyHashable] {
+		switch self {
+		case .marsEdit:
+			return [
+				"type": "marsEdit"
+			]
+		case .microblog:
+			return [
+				"type": "microblog"
+			]
+		case .twitter(let username):
+			return [
+				"type": "feed",
+				"username": username
+			]
+		}
+	}
+	
+	public init?(userInfo: [AnyHashable: AnyHashable]) {
+		guard let type = userInfo["type"] as? String else { return nil }
+		
+		switch type {
+		case "marsEdit":
+			self = ExtensionPointIdentifer.marsEdit
+		case "microblog":
+			self = ExtensionPointIdentifer.microblog
+		case "twitter":
+			guard let username = userInfo["username"] as? String else { return nil }
+			self = ExtensionPointIdentifer.twitter(username)
+		default:
+			return nil
+		}
+	}
+	
+	public func hash(into hasher: inout Hasher) {
+		switch self {
+		case .marsEdit:
+			hasher.combine("marsEdit")
+		case .microblog:
+			hasher.combine("microblog")
+		case .twitter(let username):
+			hasher.combine("twitter")
+			hasher.combine(username)
+		}
+	}
 }
 
 protocol ExtensionPoint {
diff --git a/Shared/ExtensionPoints/ExtensionPointManager.swift b/Shared/ExtensionPoints/ExtensionPointManager.swift
index ac479d47d..831dd449f 100644
--- a/Shared/ExtensionPoints/ExtensionPointManager.swift
+++ b/Shared/ExtensionPoints/ExtensionPointManager.swift
@@ -10,13 +10,20 @@ import Foundation
 import FeedProvider
 import RSCore
 
-struct ExtensionPointManager {
+final class ExtensionPointManager {
 	
 	static let shared = ExtensionPointManager()
-	
+
+	var activeExtensionPoints = [ExtensionPointIdentifer: ExtensionPoint]()
 	let availableExtensionPointTypes: [ExtensionPointType]
-//	let activeSendToCommands: [SendToCommand]
-//	let activeFeedProviders: [FeedProvider]
+	
+	var activeSendToCommands: [SendToCommand] {
+		return activeExtensionPoints.values.compactMap({ return $0 as? SendToCommand })
+	}
+	
+	var activeFeedProviders: [FeedProvider] {
+		return activeExtensionPoints.values.compactMap({ return $0 as? FeedProvider })
+	}
 	
 	init() {
 		#if os(macOS)
@@ -32,6 +39,46 @@ struct ExtensionPointManager {
 		availableExtensionPoints = [.twitter]
 		#endif
 		#endif
+		loadExtensionPointIDs()
+	}
+	
+	func activateExtensionPoint(_ extensionPointID: ExtensionPointIdentifer) {
+		activeExtensionPoints[extensionPointID] = extensionPoint(for: extensionPointID)
+		saveExtensionPointIDs()
+	}
+	
+	func deactivateExtensionPoint(_ extensionPointID: ExtensionPointIdentifer) {
+		activeExtensionPoints[extensionPointID] = nil
+		saveExtensionPointIDs()
+	}
+	
+}
+
+private extension ExtensionPointManager {
+	
+	func loadExtensionPointIDs() {
+		if let extensionPointUserInfos = AppDefaults.activeExtensionPointIDs {
+			for extensionPointUserInfo in extensionPointUserInfos {
+				if let extensionPointID = ExtensionPointIdentifer(userInfo: extensionPointUserInfo) {
+					activeExtensionPoints[extensionPointID] = extensionPoint(for: extensionPointID)
+				}
+			}
+		}
+	}
+	
+	func saveExtensionPointIDs() {
+		AppDefaults.activeExtensionPointIDs = activeExtensionPoints.keys.map({ $0.userInfo })
+	}
+	
+	func extensionPoint(for extensionPointID: ExtensionPointIdentifer) -> ExtensionPoint {
+		switch extensionPointID {
+		case .marsEdit:
+			return SendToMarsEditCommand()
+		case .microblog:
+			return SendToMicroBlogCommand()
+		case .twitter(let username):
+			return TwitterFeedProvider(username: username)
+		}
 	}
 	
 }