Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions Sources/PluginEngine/Engine/PluginEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class PluginEngine: ObservableObject {

private var fileUtils: FileUtilsProtocol!
private var nsPanelUtils: NSPanelUtilsProtocol!
private var storeUtils: StoreUtilsProtocol!
private let pluginUtils: PluginUtilsProtocol


Expand All @@ -23,9 +24,10 @@ public class PluginEngine: ObservableObject {
self.remotePluginLoader = remotePluginLoader
}

public func setup(fileUtils: FileUtilsProtocol = FileUtils(), nsPanelUtils: NSPanelUtilsProtocol = NSPanelUtils()) {
public func setup(fileUtils: FileUtilsProtocol = FileUtils(), nsPanelUtils: NSPanelUtilsProtocol = NSPanelUtils(), storeUtils: StoreUtilsProtocol = UserDefaultStore()) {
self.fileUtils = fileUtils
self.nsPanelUtils = nsPanelUtils
self.storeUtils = storeUtils
}

func handle() {
Expand Down Expand Up @@ -57,7 +59,7 @@ public extension PluginEngine {
}

func addPluginBuilder(builder: PluginBuilder) {
let plugin = builder.build(fileUtils: self.fileUtils, nsPanelUtils: self.nsPanelUtils)
let plugin = builder.build(fileUtils: self.fileUtils, nsPanelUtils: self.nsPanelUtils, storeUtils: storeUtils)
addPlugin(plugin: plugin)
}

Expand Down Expand Up @@ -87,7 +89,7 @@ public extension PluginEngine {
return nil
}
}
let plugin = self.pluginUtils.load(at: path, fileUtils: self.fileUtils, panelUtils: self.nsPanelUtils)
let plugin = self.pluginUtils.load(at: path, fileUtils: self.fileUtils, panelUtils: self.nsPanelUtils, storeUtils: storeUtils)

if autoAdd {
addPlugin(plugin: plugin)
Expand Down
6 changes: 3 additions & 3 deletions Sources/PluginEngine/Engine/Utils/PluginUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import PluginInterface
fileprivate typealias InitFunction = @convention(c) () -> UnsafeMutableRawPointer

public protocol PluginUtilsProtocol {
func load(at path: String, fileUtils: FileUtilsProtocol, panelUtils: NSPanelUtilsProtocol) -> any PluginInterfaceProtocol
func load(at path: String, fileUtils: FileUtilsProtocol, panelUtils: NSPanelUtilsProtocol, storeUtils: StoreUtilsProtocol) -> any PluginInterfaceProtocol
}

public struct PluginUtils: PluginUtilsProtocol {
public init() {}

public func load(at path: String, fileUtils: FileUtilsProtocol, panelUtils: NSPanelUtilsProtocol) -> any PluginInterfaceProtocol {
public func load(at path: String, fileUtils: FileUtilsProtocol, panelUtils: NSPanelUtilsProtocol, storeUtils: StoreUtilsProtocol) -> any PluginInterfaceProtocol {
let openRes = dlopen(path, RTLD_NOW|RTLD_LOCAL)
if openRes != nil {
defer {
Expand All @@ -31,7 +31,7 @@ public struct PluginUtils: PluginUtilsProtocol {
let f: InitFunction = unsafeBitCast(sym, to: InitFunction.self)
let pluginPointer = f()
let builder = Unmanaged<PluginBuilder>.fromOpaque(pluginPointer).takeRetainedValue()
return builder.build(fileUtils: fileUtils, nsPanelUtils: panelUtils)
return builder.build(fileUtils: fileUtils, nsPanelUtils: panelUtils, storeUtils: storeUtils)
}
else {
fatalError("error loading lib: symbol \(symbolName) not found, path: \(path)")
Expand Down
38 changes: 38 additions & 0 deletions Sources/PluginEngine/Engine/Utils/StoreUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// File.swift
//
//
// Created by Qiwei Li on 1/25/23.
//

import Foundation
import PluginInterface

public class UserDefaultStore: StoreUtilsProtocol {
internal let store = UserDefaults.standard

public init() {}

internal func getKeyName(plugin: (any PluginInterfaceProtocol)?, forKey key: String) -> String {
if let plugin = plugin {
return "\(plugin.manifest.bundleIdentifier).\(key)"
}
return key
}

public func set(_ value: Any?, forKey defaultName: String, from plugin: (any PluginInterfaceProtocol)?) {
store.set(value, forKey: getKeyName(plugin: plugin, forKey: defaultName))
}

public func removeObject(forKey defaultName: String, from plugin: (any PluginInterfaceProtocol)?) {
store.removeObject(forKey: getKeyName(plugin: plugin, forKey: defaultName))
}

public func get<T>(forKey defaultName: String, from plugin: (any PluginInterfaceProtocol)?) -> T? {
let value = store.object(forKey: getKeyName(plugin: plugin, forKey: defaultName))
if let value = value as? T {
return value
}
return nil
}
}
2 changes: 1 addition & 1 deletion Tests/PluginEngineTests/PluginEngineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class TestNSPanel: NSPanelUtilsProtocol {
}

class TestPluginUtils: PluginUtilsProtocol {
func load(at path: String, fileUtils: PluginInterface.FileUtilsProtocol, panelUtils: PluginInterface.NSPanelUtilsProtocol) -> any PluginInterfaceProtocol {
func load(at path: String, fileUtils: PluginInterface.FileUtilsProtocol, panelUtils: PluginInterface.NSPanelUtilsProtocol, storeUtils: StoreUtilsProtocol) -> any PluginInterfaceProtocol {
TestPlugin()
}
}
Expand Down
46 changes: 46 additions & 0 deletions Tests/PluginEngineTests/StoreUtilsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// StoreUtilsTests.swift
//
//
// Created by Qiwei Li on 1/25/23.
//

import XCTest
@testable import PluginEngine
import PluginInterface

struct SimpleTestPlugin: PluginInterfaceProtocol {
var id: UUID = UUID()

var manifest: ProjectManifest = ProjectManifest(displayName: "Test", bundleIdentifier: "com.test", author: "tester", shortDescription: "Testing", repository: "https://google.com", keywords: [])
}

final class StoreUtilsTests: XCTestCase {
var utils: UserDefaultStore!
var plugin: SimpleTestPlugin!

override func setUp() async throws {
utils = UserDefaultStore()
plugin = SimpleTestPlugin()
}

override func tearDown() {
utils.removeObject(forKey: "Hello", from: nil)
}

func testStoreUtils() throws {
utils.set("Hello", forKey: "Hello", from: nil)
let value: String = utils.get(forKey: "Hello", from: nil)!
XCTAssertEqual(value, "Hello")
}

func testStoreUtilsWithPlugin() throws {
// if store using plugin, then the value will be store on pluginbased
// other plugin cannot get the value
utils.set("Hello", forKey: "Hello", from: plugin)
let value: String = utils.get(forKey: "Hello", from: plugin)!
let valueWithoutPlugin: String? = utils.get(forKey: "Hello", from: nil)
XCTAssertEqual(value, "Hello")
XCTAssertNil(valueWithoutPlugin)
}
}