jan/web/plugin/PluginManager.ts
Faisal Amir 2394c13065
ui: standalone UIKit and refactor (#557)
* Eslint import order

* Initial Uikit

* Rename file with camelCase

* Remove unused code

* Remove unused code

* Set position traficlight mac

* Grouping Ribbon, Topbar and Bottombar as layout

* Added image brand

* Moving feature toggle into context folder

* Fix active state of setting menu

* Cleanup downloadModel atom helper

* Cleanup useGetConfigureModel

* Added wave animation

* Create useMainViewState intead of import helper atom

* Remove unused code

* Take a back switch ui

* Toggle using switch component

* Add dynamic primary color

* Cleanup import

* Added uikit scroll area

* Add best practice form

* Added toaster container

* Fix loader container

* Add hooks useDownloadState

* Added tooltip on ribbon menu

* Added case user multiple download model

* Adjust input style with bigger ring

* Restyle my model screen

* Replace useStartStop model with useActiveModel

* Import icon using Icon name

* Fix missing login loading start and stop model

* WIP integrate with cmdk

* Move layout search bar on middle of app

* Added function cancel download

* Cleanup model explore

* Cleanup unused code

* Move app version in bototmbar or footer

* WIP chat screen

* WIP chat screen

* Cleanup style and remove unsed code

* Added command for showing downloaded model

* Fix missing keyframe loader dot animation

* Conditional loader of plugin setting

* WIP history list message

* chore: rebase main

* Adding script ui into root package

* Fix different version react hooks form

* Add close toaster

* Added status model active or not on list of command

* Conditional showing info if user don't have a model

* Disabled toolbar chat when user not yet have convo

* chore: fix state

* fix: get resource atom

* Fix conditional bottom bar

* fix: model download state

* Fix font

* Improve icon my model

* Add toaster delete chat

* Remove test classname

* Fix scroll chat body

* Fix scrolling chat body

* chore: add message update

* Add uikit into depedencies on root package

* Update chat flow

* Fix hot reload ui changes

* Increate background color chat screen light mode

* Added visual conversation active state

* Added build:uikit on gh actions

* chore: attempt to fix CI

* fix: deps

* fix: tests

* chore: attempt to fix CI

---------

Co-authored-by: Louis <louis@jan.ai>
2023-11-07 21:27:11 +07:00

147 lines
3.8 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { JanPlugin, PluginType } from '@janhq/core'
import Plugin from './Plugin'
/**
* Manages the registration and retrieval of plugins.
*/
export class PluginManager {
// MARK: - Plugin Manager
private plugins = new Map<PluginType, JanPlugin>()
/**
* Registers a plugin.
* @param plugin - The plugin to register.
*/
register<T extends JanPlugin>(plugin: T) {
this.plugins.set(plugin.type(), plugin)
}
/**
* Retrieves a plugin by its type.
* @param type - The type of the plugin to retrieve.
* @returns The plugin, if found.
*/
get<T extends JanPlugin>(type: PluginType): T | undefined {
return this.plugins.get(type) as T | undefined
}
/**
* Loads all registered plugins.
*/
load() {
this.listPlugins().forEach((plugin) => {
plugin.onLoad()
})
}
/**
* Unloads all registered plugins.
*/
unload() {
this.listPlugins().forEach((plugin) => {
plugin.onUnload()
})
}
/**
* Retrieves a list of all registered plugins.
* @returns An array of all registered plugins.
*/
listPlugins() {
return [...this.plugins.values()]
}
/**
* Retrieves a list of all registered plugins.
* @returns An array of all registered plugins.
*/
async getActive(): Promise<Plugin[]> {
const plgList = await window.pluggableElectronIpc?.getActive()
const plugins: Plugin[] = plgList.map(
(plugin: any) =>
new Plugin(
plugin.name,
plugin.url,
plugin.active,
plugin.description,
plugin.version,
plugin.icon
)
)
return plugins
}
/**
* Register a plugin with its class.
* @param {Plugin} plugin plugin object as provided by the main process.
* @returns {void}
*/
async activatePlugin(plugin: Plugin) {
if (plugin.url)
// Import class
await import(/* webpackIgnore: true */ plugin.url).then((pluginClass) => {
// Register class if it has a default export
if (
typeof pluginClass.default === 'function' &&
pluginClass.default.prototype
) {
this.register(new pluginClass.default())
}
})
}
// MARK: - Plugin Facades
/**
* Registers all active plugins.
* @returns {void}
*/
async registerActive() {
// Get active plugins
const plugins = await this.getActive()
// Activate all
await Promise.all(
plugins.map((plugin: Plugin) => this.activatePlugin(plugin))
)
}
/**
* Install a new plugin.
* @param {Array.<installOptions | string>} plugins A list of NPM specifiers, or installation configuration objects.
* @returns {Promise.<Array.<Plugin> | false>} plugin as defined by the main process. Has property cancelled set to true if installation was cancelled in the main process.
* @alias plugins.install
*/
async install(plugins: any[]) {
if (typeof window === 'undefined') {
return
}
const plgList = await window.pluggableElectronIpc?.install(plugins)
if (plgList.cancelled) return false
return plgList.map(async (plg: any) => {
const plugin = new Plugin(plg.name, plg.url, plg.active)
await this.activatePlugin(plugin)
return plugin
})
}
/**
* Uninstall provided plugins
* @param {Array.<string>} plugins List of names of plugins to uninstall.
* @param {boolean} reload Whether to reload all renderers after updating the plugins.
* @returns {Promise.<boolean>} Whether uninstalling the plugins was successful.
* @alias plugins.uninstall
*/
uninstall(plugins: string[], reload = true) {
if (typeof window === 'undefined') {
return
}
return window.pluggableElectronIpc?.uninstall(plugins, reload)
}
}
/**
* The singleton instance of the PluginManager.
*/
export const pluginManager = new PluginManager()