commit
5800180579
20 changed files with 272 additions and 123 deletions
|
|
@ -3,16 +3,15 @@ import { App } from '../types.ts'
|
|||
|
||||
import { fullEditor } from 'prism-code-editor/setups'
|
||||
import Prism from 'prism-code-editor/prism-core'
|
||||
|
||||
import 'prismjs/components/prism-clike.js'
|
||||
import 'prismjs/components/prism-markup.js'
|
||||
import 'prismjs/components/prism-clike.js'
|
||||
import 'prismjs/components/prism-javascript.js'
|
||||
import 'prismjs/components/prism-typescript.js'
|
||||
import 'prismjs/components/prism-css.js'
|
||||
import 'prismjs/components/prism-json.js'
|
||||
import 'prismjs/components/prism-c.js'
|
||||
import 'prismjs/components/prism-csharp.js'
|
||||
import 'prismjs/components/prism-cpp.js'
|
||||
import 'prismjs/components/prism-jsx.js'
|
||||
import 'prismjs/components/prism-tsx.js'
|
||||
import 'prism-code-editor/languages'
|
||||
import 'prism-code-editor/prism-markdown'
|
||||
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
|
||||
interface EditorConfig {
|
||||
|
|
@ -20,15 +19,18 @@ interface EditorConfig {
|
|||
}
|
||||
|
||||
export default class EditorApp implements App {
|
||||
name = 'Editor'
|
||||
pkg = 'flow.editor'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
meta = {
|
||||
name: 'Editor',
|
||||
description: 'A simple editor app.',
|
||||
pkg: 'flow.editor',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (data?: EditorConfig): Promise<FlowWindow> {
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 500,
|
||||
height: 400
|
||||
})
|
||||
|
|
@ -125,12 +127,76 @@ export default class EditorApp implements App {
|
|||
}
|
||||
})
|
||||
|
||||
let language
|
||||
|
||||
switch (data.path.split('.').at(-1)?.toLowerCase()) {
|
||||
case 'c':
|
||||
case 'cs':
|
||||
case 'cpp':
|
||||
case 'java': {
|
||||
language = 'clike'
|
||||
break
|
||||
}
|
||||
|
||||
case 'ts': {
|
||||
language = 'typescript'
|
||||
break
|
||||
}
|
||||
|
||||
case 'js':
|
||||
case 'mjs':
|
||||
case 'cjs': {
|
||||
language = 'javascript'
|
||||
break
|
||||
}
|
||||
|
||||
case 'jsx': {
|
||||
language = 'jsx'
|
||||
break
|
||||
}
|
||||
|
||||
case 'tsx': {
|
||||
language = 'tsx'
|
||||
break
|
||||
}
|
||||
|
||||
case 'html': {
|
||||
language = 'html'
|
||||
break
|
||||
}
|
||||
|
||||
case 'md': {
|
||||
language = 'md'
|
||||
break
|
||||
}
|
||||
|
||||
case 'css': {
|
||||
language = 'css'
|
||||
break
|
||||
}
|
||||
|
||||
case 'xml': {
|
||||
language = 'xml'
|
||||
break
|
||||
}
|
||||
|
||||
case 'py': {
|
||||
language = 'python'
|
||||
break
|
||||
}
|
||||
|
||||
default: {
|
||||
language = 'text'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const value = (await window.fs.promises.readFile(data.path)).toString()
|
||||
const editor = fullEditor(
|
||||
Prism,
|
||||
win.content.querySelector('.editor'),
|
||||
{
|
||||
language: data.path.split('.').at(-1),
|
||||
language,
|
||||
theme: 'github-dark',
|
||||
value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,18 @@ import { FlowWindow } from '../wm.ts'
|
|||
import { Stats } from 'fs'
|
||||
|
||||
export default class FilesApp implements App {
|
||||
name = 'Files'
|
||||
pkg = 'flow.files'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
meta = {
|
||||
name: 'Files',
|
||||
description: 'A simple files app.',
|
||||
pkg: 'flow.files',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 500,
|
||||
height: 400
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,17 +3,19 @@ import { App, PackageJSON } from '../types.ts'
|
|||
import { FlowWindow } from '../wm.ts'
|
||||
|
||||
export default class SettingsApp implements App {
|
||||
name = 'Info'
|
||||
pkg = 'flow.info'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
canResize = true
|
||||
meta = {
|
||||
name: 'Info',
|
||||
description: 'FlowOS Information.',
|
||||
pkg: 'flow.info',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const packageJSON: PackageJSON = await import('../../package.json')
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 300,
|
||||
height: 400,
|
||||
canResize: false
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
import icon from '../assets/icons/manager.png'
|
||||
import { App } from '../types.ts'
|
||||
import { App, LoadedApp, LoadedPlugin } from '../types.ts'
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import nullIcon from '../assets/icons/null.png'
|
||||
|
||||
export default class ManagerApp implements App {
|
||||
name = 'Manager'
|
||||
pkg = 'flow.manager'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
meta = {
|
||||
name: 'Flow Manager',
|
||||
description: 'A FlowOS utility app.',
|
||||
pkg: 'flow.manager',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 350,
|
||||
height: 500
|
||||
})
|
||||
|
|
@ -22,13 +26,24 @@ export default class ManagerApp implements App {
|
|||
win.content.style.padding = '10px'
|
||||
win.content.style.background = 'var(--base)'
|
||||
win.content.innerHTML = `
|
||||
${window.flow.apps.map(app => {
|
||||
${window.flow.apps.map((app: LoadedApp) => {
|
||||
return `
|
||||
<div style="display:flex;gap: 10px;padding: 10px;background: var(--surface-0);border-radius: 10px;">
|
||||
<img src="${app.icon}" style="border-radius: 40%;aspect-ratio: 1 / 1;height: 50px;"/>
|
||||
<img src="${app.meta.icon}" style="border-radius: 40%;aspect-ratio: 1 / 1;height: 50px;"/>
|
||||
<div>
|
||||
<h3 style="margin:0;">${app.name} ${(app.builtin ?? false) ? '<code style="font-size: 0.75em;">(builtin)</code>' : ''}</h3>
|
||||
<p style="margin:0;">${app.pkg} (v${app.version})</p>
|
||||
<h3 style="margin:0;">${app.meta.name} ${(app.builtin ?? false) ? '<code style="font-size: 0.75em;">(builtin)</code>' : ''}</h3>
|
||||
<p style="margin:0;">${app.meta.pkg} (v${app.meta.version}) - App</p>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}).join('')}
|
||||
${window.flow.plugins.map((plugin: LoadedPlugin) => {
|
||||
return `
|
||||
<div style="display:flex;gap: 10px;padding: 10px;background: var(--surface-0);border-radius: 10px;">
|
||||
<img src="${plugin.meta.icon ?? nullIcon}" style="border-radius: 100%;aspect-ratio: 1 / 1;height: 50px;"/>
|
||||
<div>
|
||||
<h3 style="margin:0;">${plugin.meta.name} ${(plugin.builtin ?? false) ? '<code style="font-size: 0.75em;">(builtin)</code>' : ''}</h3>
|
||||
<p style="margin:0;">${plugin.meta.pkg} (v${plugin.meta.version}) - Plugin</p>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
|
|
|||
|
|
@ -3,15 +3,18 @@ import { App } from '../types.ts'
|
|||
import { FlowWindow } from '../wm.ts'
|
||||
|
||||
export default class MusicApp implements App {
|
||||
name = 'Music'
|
||||
pkg = 'flow.music'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
meta = {
|
||||
name: 'Music',
|
||||
description: 'A simple music app.',
|
||||
pkg: 'flow.music',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 700,
|
||||
height: 300
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,15 +3,18 @@ import { App } from '../types.ts'
|
|||
import { FlowWindow } from '../wm.ts'
|
||||
|
||||
export default class SettingsApp implements App {
|
||||
name = 'Settings'
|
||||
pkg = 'flow.settings'
|
||||
icon = icon
|
||||
version = '1.0.0'
|
||||
meta = {
|
||||
name: 'Settings',
|
||||
description: 'Modify/customize FlowOS.',
|
||||
pkg: 'flow.settings',
|
||||
version: '1.0.0',
|
||||
icon
|
||||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const win = window.wm.createWindow({
|
||||
title: this.name,
|
||||
icon,
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
width: 700,
|
||||
height: 300
|
||||
})
|
||||
|
|
|
|||
BIN
src/assets/icons/null.png
Normal file
BIN
src/assets/icons/null.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
5
src/files.d.ts
vendored
5
src/files.d.ts
vendored
|
|
@ -1,2 +1,5 @@
|
|||
declare module '*.png'
|
||||
declare module '*.png' {
|
||||
const image: string
|
||||
export = image
|
||||
}
|
||||
declare module '*.json'
|
||||
|
|
|
|||
68
src/flow.ts
68
src/flow.ts
|
|
@ -1,4 +1,4 @@
|
|||
import { App, LoadedApp } from './types.ts'
|
||||
import { LoadedApp, LoadedPlugin } from './types.ts'
|
||||
|
||||
class Flow {
|
||||
apps: LoadedApp[] = []
|
||||
|
|
@ -11,17 +11,30 @@ class Flow {
|
|||
'manager'
|
||||
]
|
||||
|
||||
async init (): Promise<void> {
|
||||
plugins: LoadedPlugin[] = []
|
||||
pluginList: string[] = [
|
||||
'appLauncher',
|
||||
'apps',
|
||||
'weather',
|
||||
'clock',
|
||||
'switcher',
|
||||
'battery'
|
||||
]
|
||||
|
||||
private async initApps (): Promise<void> {
|
||||
window.preloader.setPending('apps')
|
||||
window.preloader.setStatus('importing default apps...')
|
||||
|
||||
for (const appPath of this.appList) {
|
||||
const { default: ImportedApp } = await import(`./apps/${appPath}.ts`)
|
||||
window.preloader.setStatus(`importing default apps\n${appPath}`)
|
||||
const { default: ImportedApp } = await import(`./apps/${appPath}.ts`).catch((e: Error) => {
|
||||
console.error(e)
|
||||
window.preloader.setStatus(`unable to import ${appPath}\n${e.name}: ${e.message}`)
|
||||
})
|
||||
const app = new ImportedApp()
|
||||
app.builtin = true
|
||||
|
||||
window.preloader.setStatus(`importing default apps\n${appPath}`)
|
||||
this.add(app)
|
||||
this.addApp(app)
|
||||
}
|
||||
|
||||
window.wm.launcher.style.opacity = '0'
|
||||
|
|
@ -31,13 +44,13 @@ class Flow {
|
|||
window.preloader.setStatus('adding apps to app launcher...')
|
||||
|
||||
this.apps.forEach((app) => {
|
||||
window.preloader.setStatus(`adding apps to app launcher\n${app.name}`)
|
||||
window.preloader.setStatus(`adding apps to app launcher\n${app.meta.name}`)
|
||||
const appElement = document.createElement('app')
|
||||
appElement.onclick = async () => {
|
||||
await window.flow.openApp(app.pkg)
|
||||
await window.flow.openApp(app.meta.pkg)
|
||||
window.wm.toggleLauncher()
|
||||
}
|
||||
appElement.innerHTML = `<img src="${app.icon}"><div>${app.name}</div>`
|
||||
appElement.innerHTML = `<img src="${app.meta.icon}"><div>${app.meta.name}</div>`
|
||||
window.wm.launcher.querySelector('apps')?.appendChild(appElement)
|
||||
})
|
||||
|
||||
|
|
@ -47,17 +60,48 @@ class Flow {
|
|||
await window.preloader.setDone('apps')
|
||||
}
|
||||
|
||||
add (app: App): void {
|
||||
if (this.apps.some(x => x.pkg === app.pkg)) {
|
||||
console.error(`Unable to register app; ${app.pkg} is already registered.`)
|
||||
private async initPlugins (): Promise<void> {
|
||||
window.preloader.setPending('plugins')
|
||||
window.preloader.setStatus('importing default plugins...')
|
||||
|
||||
for (const pluginPath of this.pluginList) {
|
||||
window.preloader.setStatus(`importing default plugins\n${pluginPath}`)
|
||||
const plugin = await import(`./plugins/${pluginPath}.ts`).catch((e: Error) => {
|
||||
console.error(e)
|
||||
window.preloader.setStatus(`unable to import ${pluginPath}\n${e.name}: ${e.message}`)
|
||||
})
|
||||
const loadedPlugin = {
|
||||
...plugin,
|
||||
builtin: true
|
||||
}
|
||||
this.addPlugin(loadedPlugin)
|
||||
}
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
await this.initApps()
|
||||
await this.initPlugins()
|
||||
}
|
||||
|
||||
addApp (app: LoadedApp): void {
|
||||
if (this.apps.some(x => x.meta.pkg === app.meta.pkg)) {
|
||||
console.error(`Unable to register app; ${app.meta.pkg} is already registered.`)
|
||||
return
|
||||
}
|
||||
|
||||
this.apps.push(app)
|
||||
}
|
||||
|
||||
addPlugin (plugin: LoadedPlugin): void {
|
||||
if (window.flow.plugins.some(x => x.meta.pkg === plugin.meta.pkg)) {
|
||||
console.error(`Unable to register tool; ${plugin.meta.pkg} is already registered.`)
|
||||
return
|
||||
}
|
||||
this.plugins.push(plugin)
|
||||
}
|
||||
|
||||
async openApp (pkg: string, data?: any): Promise<void> {
|
||||
const app = this.apps.find(x => x.pkg === pkg)
|
||||
const app = this.apps.find(x => x.meta.pkg === pkg)
|
||||
const win = app?.open(data)
|
||||
const event = new CustomEvent('app_opened', { detail: { app, win: await win } })
|
||||
window.dispatchEvent(event)
|
||||
|
|
|
|||
|
|
@ -39,10 +39,9 @@ window.wm = new WM();
|
|||
window.fs = new (window as any).Filer.FileSystem()
|
||||
await window.preloader.setDone('filesystem')
|
||||
|
||||
await window.statusBar.init()
|
||||
await window.wm.init()
|
||||
|
||||
await window.flow.init()
|
||||
await window.statusBar.init()
|
||||
|
||||
window.preloader.setStatus('')
|
||||
window.preloader.finish()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
export const meta = {
|
||||
name: 'App Launcher',
|
||||
description: 'Opens the app launcher.',
|
||||
id: 'applauncher'
|
||||
pkg: 'flow.applauncher',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -3,7 +3,8 @@ import { AppOpenedEvent, AppClosedEvent } from '../types'
|
|||
export const meta = {
|
||||
name: 'Apps',
|
||||
description: 'Displays the current apps open.',
|
||||
id: 'apps'
|
||||
pkg: 'flow.apps',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -19,7 +20,7 @@ export const run = (element: HTMLDivElement): void => {
|
|||
appIcon.style.background = 'var(--surface-0)'
|
||||
appIcon.style.padding = '5px 7.5px'
|
||||
appIcon.style.borderRadius = '5px'
|
||||
appIcon.innerHTML = `<img data-id="${win.id}" src="${app.icon}"/> ${app.name}`
|
||||
appIcon.innerHTML = `<img data-id="${win.id}" src="${app.meta.icon}"/> ${app.meta.name}`
|
||||
appIcon.onclick = async () => {
|
||||
const win = await e.detail.win
|
||||
win.focus()
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export const meta = {
|
||||
name: 'Battery',
|
||||
description: 'Tells you your device\'s battery.',
|
||||
id: 'battery'
|
||||
pkg: 'flow.battery',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export const meta = {
|
||||
name: 'Clock',
|
||||
description: 'Displays the date & time.',
|
||||
id: 'clock'
|
||||
pkg: 'flow.clock',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export const meta = {
|
||||
name: 'Desktop Switcher',
|
||||
description: 'Allows you to switch between desktops.',
|
||||
id: 'switcher'
|
||||
pkg: 'flow.switcher',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export const meta = {
|
||||
name: 'Weather',
|
||||
description: 'Tells you the weather.',
|
||||
id: 'weather'
|
||||
pkg: 'flow.weather',
|
||||
version: '1.0.0'
|
||||
}
|
||||
|
||||
export const run = (element: HTMLDivElement): void => {
|
||||
|
|
@ -7,7 +7,7 @@ class Preloader {
|
|||
this.element = document.createElement('preloader')
|
||||
|
||||
this.element.innerHTML = `
|
||||
<img src="${flowIcon as string}" width="150px">
|
||||
<img src="${flowIcon}" width="150px">
|
||||
<div class="done"></div>
|
||||
<div class="status"></div>
|
||||
`
|
||||
|
|
|
|||
|
|
@ -1,17 +1,7 @@
|
|||
|
||||
import { StatusItem } from './types'
|
||||
import { Plugin } from './types'
|
||||
|
||||
class StatusBar {
|
||||
pluginList: string[] = [
|
||||
'appLauncher',
|
||||
'apps',
|
||||
'weather',
|
||||
'clock',
|
||||
'switcher',
|
||||
'battery'
|
||||
]
|
||||
|
||||
plugins: StatusItem[] = []
|
||||
element: HTMLElement
|
||||
|
||||
constructor () {
|
||||
|
|
@ -20,30 +10,21 @@ class StatusBar {
|
|||
document.body.appendChild(this.element)
|
||||
}
|
||||
|
||||
add (item: StatusItem): void {
|
||||
if (this.plugins.some(x => x.meta.id === item.meta.id)) {
|
||||
console.error(`Unable to register tool; ${item.meta.id} is already registered.`)
|
||||
return
|
||||
}
|
||||
|
||||
async add (item: Plugin): Promise<void> {
|
||||
const element = document.createElement('div')
|
||||
element.setAttribute('data-toolbar-id', item.meta.id)
|
||||
element.setAttribute('data-toolbar-id', item.meta.pkg)
|
||||
|
||||
this.plugins.push(item)
|
||||
this.element.appendChild(element)
|
||||
|
||||
item.run(element)
|
||||
await item.run(element)
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
window.preloader.setPending('plugins')
|
||||
window.preloader.setStatus('importing default plugins...')
|
||||
window.preloader.setStatus('adding plugins to statusbar...')
|
||||
|
||||
for (const pluginPath of this.pluginList) {
|
||||
const plugin = await import(`./modules/${pluginPath}.ts`)
|
||||
|
||||
window.preloader.setStatus(`importing default plugins\n${pluginPath}`)
|
||||
this.add(plugin)
|
||||
for (const plugin of window.flow.plugins) {
|
||||
window.preloader.setStatus(`adding plugins to statusbar\n${plugin.meta.pkg}`)
|
||||
await this.add(plugin)
|
||||
}
|
||||
|
||||
await window.preloader.setDone('plugins')
|
||||
|
|
|
|||
|
|
@ -143,24 +143,36 @@ launcher {
|
|||
max-height: 70vh;
|
||||
padding: 20px;
|
||||
margin: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(125px, 1fr));
|
||||
grid-template-rows: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 40px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
app {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
height: max-content;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 75px;
|
||||
width: 100%;
|
||||
border-radius: 40%;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
div {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: fit-content;
|
||||
height: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
52
src/types.ts
52
src/types.ts
|
|
@ -1,29 +1,9 @@
|
|||
import { FlowWindow } from './wm'
|
||||
|
||||
export interface StatusItem {
|
||||
meta: {
|
||||
name: string
|
||||
description: string
|
||||
id: string
|
||||
}
|
||||
run: Function
|
||||
}
|
||||
|
||||
export interface PackageJSON {
|
||||
version: string
|
||||
}
|
||||
|
||||
export interface App {
|
||||
name: string
|
||||
pkg: string
|
||||
|
||||
version: string
|
||||
|
||||
icon: string
|
||||
|
||||
open: (data: any) => Promise<FlowWindow>
|
||||
}
|
||||
|
||||
export interface AppOpenedEvent extends CustomEvent {
|
||||
detail: {
|
||||
app: App
|
||||
|
|
@ -50,10 +30,42 @@ export interface FlowWindowConfig {
|
|||
minHeight?: number
|
||||
}
|
||||
|
||||
export interface App {
|
||||
meta: {
|
||||
name: string
|
||||
description: string
|
||||
pkg: string
|
||||
version: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
open: (data: any) => Promise<FlowWindow>
|
||||
}
|
||||
|
||||
export interface Plugin {
|
||||
meta: {
|
||||
name: string
|
||||
description: string
|
||||
pkg: string
|
||||
version: string
|
||||
icon?: string
|
||||
}
|
||||
|
||||
run: (element: HTMLDivElement) => void | Promise<void>
|
||||
}
|
||||
|
||||
export interface Apps {
|
||||
[key: string]: App
|
||||
}
|
||||
|
||||
export interface Plugins {
|
||||
[key: string]: Plugin
|
||||
}
|
||||
|
||||
export interface LoadedApp extends App {
|
||||
builtin: boolean
|
||||
}
|
||||
|
||||
export interface LoadedPlugin extends Plugin {
|
||||
builtin: boolean
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue