diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index 3e92e3d..c6f4f41 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -14,6 +14,7 @@ import fspExistsIpcInvoke from './invokes/fspExists'; import fspMkdirIpcInvoke from './invokes/fspMkdir'; import fspWriteFileIpcInvoke from './invokes/fspWriteFile'; import getXtoryTemplatesIpcInvoke from './invokes/getXtoryTemplates'; +import getFileTypesIpcInvoke from './invokes/getFileTypes'; import openProjectIpcInvoke from './invokes/openProject'; const on = (channel: ChannelsMain, ipcAction: IpcAction): void => { @@ -36,4 +37,5 @@ handle(ChannelsMain.fspExists, fspExistsIpcInvoke); handle(ChannelsMain.fspMkdir, fspMkdirIpcInvoke); handle(ChannelsMain.fspWriteFile, fspWriteFileIpcInvoke); handle(ChannelsMain.getXtoryTemplates, getXtoryTemplatesIpcInvoke); +handle(ChannelsMain.getFileTypes, getFileTypesIpcInvoke); handle(ChannelsMain.openProject, openProjectIpcInvoke); diff --git a/src/main/ipc/invokes/getFileTypes.ts b/src/main/ipc/invokes/getFileTypes.ts new file mode 100644 index 0000000..72c56a6 --- /dev/null +++ b/src/main/ipc/invokes/getFileTypes.ts @@ -0,0 +1,13 @@ +import { IpcMainInvokeEvent } from 'electron'; +import project from 'main/project'; + +export default async function getFileTypes( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + event: IpcMainInvokeEvent, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _: undefined +): Promise { + const pluginsService = project.pluginsService; + const fileTypes = pluginsService.getFileTypePlugins(); + return ['ok']; +} diff --git a/src/main/project/index.ts b/src/main/project/index.ts index 45a5515..c9b49c4 100644 --- a/src/main/project/index.ts +++ b/src/main/project/index.ts @@ -1,6 +1,7 @@ import { WebContents } from 'electron'; -import LoggingService from 'main/services/loggingService'; +import type LoggingService from 'main/services/loggingService'; +import type PluginsService from 'main/services/pluginsService'; import { ChannelsRenderer, @@ -35,6 +36,14 @@ export default class ProjectManager { return this.#project.loggingService; } + static get pluginsService(): PluginsService { + this.#throwIfNotInit(); + if (!this.#project) { + throw Error('No Project Is Open!'); + } + return this.#project.pluginsService; + } + static init(projectLoader: ProjectLoaderType) { if (this.#isInit) { throw new Error( diff --git a/src/main/services/pluginsService/index.ts b/src/main/services/pluginsService/index.ts index f92ac1b..4b29c9a 100644 --- a/src/main/services/pluginsService/index.ts +++ b/src/main/services/pluginsService/index.ts @@ -6,7 +6,7 @@ import project from 'main/project'; import { LogLevel } from 'shared/types'; import { sanitizePath, tryGetAsync } from 'shared/utils'; -import PluginBuilder from './pluginBuilder'; +import PluginApi from './pluginApi'; import IService from '../IService'; @@ -26,7 +26,6 @@ class PluginsService implements IService { this.#plugins = {}; try { await this.loadPlugins(); - console.log(this.#plugins); return true; } catch (error) { return false; @@ -85,6 +84,12 @@ class PluginsService implements IService { return true; } + // TODO: consider better naming + getFileTypePlugins() { + const plugins = this.#plugins; + console.log(plugins); + } + // eslint-disable-next-line class-methods-use-this async #runMainScript(pluginName: string, scriptPath: string): Promise { const context = { @@ -93,7 +98,7 @@ class PluginsService implements IService { return `Required ${path}`; }, logger: project.logger, - builder: new PluginBuilder(), + api: new PluginApi(), }; const script = await readFile(scriptPath, 'utf8'); @@ -101,7 +106,7 @@ class PluginsService implements IService { try { // eslint-disable-next-line no-new-func new Function(`with(this) { ${script} }`).call(context); - const plugin = context.builder.build(); + const plugin = context.api.build(); this.#plugins[pluginName] = plugin; } catch (error) { project.logger.log(LogLevel.error, ['plugin', pluginName], error); diff --git a/src/main/services/pluginsService/pluginApi.ts b/src/main/services/pluginsService/pluginApi.ts new file mode 100644 index 0000000..9d85242 --- /dev/null +++ b/src/main/services/pluginsService/pluginApi.ts @@ -0,0 +1,50 @@ +type ConnectionInfo = { + in: number; + out: number; +}; + +type NodeInfo = { + type: string; + connection: ConnectionInfo; +}; + +// builder.flowView.setFileType('xxx') // *.xxx +// builder.flowView.setNodes(xxx) +// builder.globalShortcut.setShortcutAction(yyy) + +class FlowViewBuilder { + #fileType: string | null = null; + + #nodes: NodeInfo[] | null = null; + + setFileType(extension: string) { + this.#fileType = extension; + return this; + } + + setNodes(nodes: NodeInfo[]) { + this.#nodes = nodes; + return this; + } + + // TODO: making these build functions private can help with a well constructed API + build() { + const fileType = this.#fileType; + const nodes = this.#nodes; + return { fileType, nodes }; + } +} + +export default class PluginBuilder { + flowView: FlowViewBuilder; + + constructor() { + this.flowView = new FlowViewBuilder(); + } + + build() { + const flowViewBuilder = this.flowView; + const flowView = flowViewBuilder.build(); + return { flowView }; + } +} diff --git a/src/main/services/pluginsService/pluginBuilder.ts b/src/main/services/pluginsService/pluginBuilder.ts deleted file mode 100644 index 0dbbf78..0000000 --- a/src/main/services/pluginsService/pluginBuilder.ts +++ /dev/null @@ -1,31 +0,0 @@ -type ConnectionInfo = { - in: number; - out: number; -}; - -type NodeInfo = { - type: string; - connection: ConnectionInfo; -}; - -export default class PluginBuilder { - #flowView: boolean = false; - - #nodes: NodeInfo | undefined = undefined; - - setFlowView(value: boolean) { - this.#flowView = value; - return this; - } - - setNodes(nodes: NodeInfo) { - this.#nodes = nodes; - return this; - } - - build() { - const flowView = this.#flowView; - const nodes = this.#nodes; - return { flowView, nodes }; - } -} diff --git a/src/renderer/components/Tab/TabView.tsx b/src/renderer/components/Tab/TabView.tsx index bbc6402..1a5079f 100644 --- a/src/renderer/components/Tab/TabView.tsx +++ b/src/renderer/components/Tab/TabView.tsx @@ -3,6 +3,8 @@ import React from 'react'; import Box from '@mui/material/Box'; import TextField from '@mui/material/TextField'; +import { ChannelsMain } from 'shared/types'; + import { useAppSelector, useAppDispatch } from 'renderer/state/store/index'; import { setTabData, @@ -20,6 +22,17 @@ export interface TabViewProps { export default function TabView({ tabId }: TabViewProps) { const dispatch = useAppDispatch(); + const [fileTypes, setFileTypes] = React.useState([]); + + React.useEffect(() => { + async function getFileTypes() { + const result: string[] = await window.electron.ipcRenderer.invoke( + ChannelsMain.getFileTypes + ); + setFileTypes(result); + } + getFileTypes().catch(e => console.log('eee', e)); + }, []); const tabState = useAppSelector( (state) => state.tabsState.tabs.find((tab) => tab.id === tabId)! @@ -32,6 +45,7 @@ export default function TabView({ tabId }: TabViewProps) { [dispatch, tabId] ); const dispatchFileView = () => { + console.log(fileTypes, 'fileTypes') if (tabData.extension === 'xflow') { return ; } diff --git a/src/shared/types/channels.ts b/src/shared/types/channels.ts index 03d516e..bd461ac 100644 --- a/src/shared/types/channels.ts +++ b/src/shared/types/channels.ts @@ -2,6 +2,7 @@ export enum ChannelsMain { browseFileSystem = 'browseFileSystem', createNewProject = 'createNewProject', getXtoryTemplates = 'getXtoryTemplates', + getFileTypes = 'getFileTypes', openProject = 'openProject', openFileAsTab = 'openFileAsTab', fspExists = 'fspExists',