[🎨] Major codebase overhaul
This commit is contained in:
parent
c994212bbc
commit
faa5c87b3b
23 changed files with 257 additions and 151 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "flow-os",
|
||||
"name": "flowos",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "flow-os",
|
||||
"name": "flowos",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "flow-os",
|
||||
"name": "flowos",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "The future of FlowOS.",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "ts-standard",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import icon from '../assets/icons/null.png'
|
||||
import { App } from '../types.ts'
|
||||
import icon from '../../assets/icons/null.png'
|
||||
import { App } from '../../types'
|
||||
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
export default class BrowserApp implements App {
|
||||
meta = {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import icon from '../assets/icons/editor.png'
|
||||
import { App } from '../types.ts'
|
||||
import icon from '../../assets/icons/editor.png'
|
||||
import { App } from '../../types'
|
||||
|
||||
import { fullEditor } from 'prism-code-editor/setups'
|
||||
// this will also import markup, clike, javascript, typescript and jsx
|
||||
|
|
@ -8,7 +8,7 @@ import 'prism-code-editor/grammars/css-extras'
|
|||
import 'prism-code-editor/grammars/markdown'
|
||||
import 'prism-code-editor/grammars/python'
|
||||
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
interface EditorConfig {
|
||||
path: string
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import icon from '../assets/icons/files.png'
|
||||
import { App } from '../types.ts'
|
||||
import icon from '../../assets/icons/files.png'
|
||||
import { App } from '../../types'
|
||||
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
import { Stats } from 'fs'
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import icon from '../assets/icons/info.png'
|
||||
import badge from '../assets/badge.png'
|
||||
import { App, PackageJSON } from '../types.ts'
|
||||
import icon from '../../assets/icons/info.png'
|
||||
import badge from '../../assets/badge.png'
|
||||
import { App, PackageJSON } from '../../types'
|
||||
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
export default class InfoApp implements App {
|
||||
meta = {
|
||||
|
|
@ -14,7 +14,7 @@ export default class InfoApp implements App {
|
|||
}
|
||||
|
||||
async open (): Promise<FlowWindow> {
|
||||
const packageJSON: PackageJSON = await import('../../package.json')
|
||||
const packageJSON: PackageJSON = await import('../../../package.json')
|
||||
const win = window.wm.createWindow({
|
||||
title: this.meta.name,
|
||||
icon: this.meta.icon,
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import icon from '../assets/icons/manager.png'
|
||||
import { App, LoadedApp, LoadedPlugin } from '../types.ts'
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import nullIcon from '../assets/icons/null.png'
|
||||
import icon from '../../assets/icons/manager.png'
|
||||
import { App, LoadedApp, LoadedPlugin } from '../../types'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
import nullIcon from '../../assets/icons/null.png'
|
||||
|
||||
export default class ManagerApp implements App {
|
||||
meta = {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import icon from '../assets/icons/music.png'
|
||||
import { App } from '../types.ts'
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import icon from '../../assets/icons/music.png'
|
||||
import { App } from '../../types'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
export default class MusicApp implements App {
|
||||
meta = {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import icon from '../assets/icons/settings.png'
|
||||
import { App } from '../types.ts'
|
||||
import { FlowWindow } from '../wm.ts'
|
||||
import icon from '../../assets/icons/settings.png'
|
||||
import { App } from '../../types'
|
||||
import FlowWindow from '../../structures/FlowWindow'
|
||||
|
||||
export default class SettingsApp implements App {
|
||||
meta = {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { AppOpenedEvent, AppClosedEvent } from '../types'
|
||||
import { AppOpenedEvent, AppClosedEvent } from '../../types'
|
||||
|
||||
export const meta = {
|
||||
name: 'Apps',
|
||||
14
src/index.ts
14
src/index.ts
|
|
@ -1,9 +1,9 @@
|
|||
import './style.less'
|
||||
import './assets/style.less'
|
||||
|
||||
import Preloader from './preloader'
|
||||
import StatusBar from './statusbar'
|
||||
import WM from './wm'
|
||||
import Flow from './flow'
|
||||
import Preloader from './instances/Preloader'
|
||||
import StatusBar from './instances/StatusBar'
|
||||
import WindowManager from './instances/WindowManager'
|
||||
import Flow from './instances/Flow'
|
||||
|
||||
import * as fs from 'fs'
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ declare global {
|
|||
flow: Flow
|
||||
fs: typeof fs
|
||||
statusBar: StatusBar
|
||||
wm: WM
|
||||
wm: WindowManager
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ if (params.get('debug') !== null && params.get('debug') !== undefined) {
|
|||
window.preloader = new Preloader()
|
||||
window.flow = new Flow()
|
||||
window.statusBar = new StatusBar()
|
||||
window.wm = new WM();
|
||||
window.wm = new WindowManager();
|
||||
|
||||
(async function () {
|
||||
window.preloader.setPending('filesystem')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { LoadedApp, LoadedPlugin } from './types.ts'
|
||||
import { LoadedApp, LoadedPlugin } from '../types'
|
||||
|
||||
class Flow {
|
||||
apps: LoadedApp[] = []
|
||||
|
|
@ -22,13 +22,16 @@ class Flow {
|
|||
'battery'
|
||||
]
|
||||
|
||||
/**
|
||||
* Initiates applications.
|
||||
*/
|
||||
private async initApps (): Promise<void> {
|
||||
window.preloader.setPending('apps')
|
||||
window.preloader.setStatus('importing default apps...')
|
||||
|
||||
for (const appPath of this.appList) {
|
||||
window.preloader.setStatus(`importing default apps\n${appPath}`)
|
||||
const { default: ImportedApp } = await import(`./apps/${appPath}.ts`).catch((e: Error) => {
|
||||
const { default: ImportedApp } = await import(`../builtin/apps/${appPath}.ts`).catch((e: Error) => {
|
||||
console.error(e)
|
||||
window.preloader.setStatus(`unable to import ${appPath}\n${e.name}: ${e.message}`)
|
||||
})
|
||||
|
|
@ -61,13 +64,16 @@ class Flow {
|
|||
await window.preloader.setDone('apps')
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates plugins.
|
||||
*/
|
||||
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) => {
|
||||
const plugin = await import(`../builtin/plugins/${pluginPath}.ts`).catch((e: Error) => {
|
||||
console.error(e)
|
||||
window.preloader.setStatus(`unable to import ${pluginPath}\n${e.name}: ${e.message}`)
|
||||
})
|
||||
|
|
@ -79,11 +85,19 @@ class Flow {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the Flow session.
|
||||
*/
|
||||
async init (): Promise<void> {
|
||||
await this.initApps()
|
||||
await this.initPlugins()
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an app.
|
||||
*
|
||||
* @param app The app to be registered.
|
||||
*/
|
||||
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.`)
|
||||
|
|
@ -93,6 +107,11 @@ class Flow {
|
|||
this.apps.push(app)
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin.
|
||||
*
|
||||
* @param plugin The plugin to be registered.
|
||||
*/
|
||||
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.`)
|
||||
|
|
@ -101,6 +120,12 @@ class Flow {
|
|||
this.plugins.push(plugin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a registered application.
|
||||
*
|
||||
* @param pkg The PKG ID of the application.
|
||||
* @param data Payload info for app to recieve.
|
||||
*/
|
||||
async openApp (pkg: string, data?: any): Promise<void> {
|
||||
const app = this.apps.find(x => x.meta.pkg === pkg)
|
||||
const win = app?.open(data)
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
import flowIcon from './assets/flow.png'
|
||||
import flowIcon from '../assets/flow.png'
|
||||
|
||||
class Preloader {
|
||||
element: HTMLElement
|
||||
|
||||
/**
|
||||
* Creates the preloader.
|
||||
*/
|
||||
constructor () {
|
||||
this.element = document.createElement('preloader')
|
||||
|
||||
|
|
@ -15,14 +18,29 @@ class Preloader {
|
|||
document.body.appendChild(this.element)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status text of the preloader.
|
||||
*
|
||||
* @param value The preloader status text.
|
||||
*/
|
||||
setStatus (value: string): void {
|
||||
(this.element.querySelector('.status') as HTMLElement).innerText = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets loading state of an instance to pending.
|
||||
*
|
||||
* @param value The name of an instance.
|
||||
*/
|
||||
setPending (value: string): void {
|
||||
(this.element.querySelector('.done') as HTMLElement).innerHTML += `<div class="${value.split(' ').join('-')}"><i class='icon bx bx-minus' ></i>${value}</div>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets loading state of an instance to done.
|
||||
*
|
||||
* @param value The name of an instance.
|
||||
*/
|
||||
async setDone (value: string): Promise<void> {
|
||||
const icon = this.element.querySelector('.done')?.querySelector(`.${value.split(' ').join('-')}`)?.querySelector('.icon')
|
||||
icon?.classList.remove('bx-minus')
|
||||
|
|
@ -30,6 +48,9 @@ class Preloader {
|
|||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the preloader.
|
||||
*/
|
||||
finish (): void {
|
||||
this.element.style.opacity = '0'
|
||||
this.element.style.pointerEvents = 'none'
|
||||
|
|
@ -1,15 +1,23 @@
|
|||
|
||||
import { Plugin } from './types'
|
||||
import { Plugin } from '../types'
|
||||
|
||||
class StatusBar {
|
||||
element: HTMLElement
|
||||
|
||||
/**
|
||||
* Creates the status bar.
|
||||
*/
|
||||
constructor () {
|
||||
this.element = document.createElement('toolbar')
|
||||
|
||||
document.body.appendChild(this.element)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a plugin to the status bar.
|
||||
*
|
||||
* @param item The plugin to be added to the status bar.
|
||||
*/
|
||||
async add (item: Plugin): Promise<void> {
|
||||
const element = document.createElement('div')
|
||||
element.setAttribute('data-toolbar-id', item.meta.pkg)
|
||||
|
|
@ -19,6 +27,9 @@ class StatusBar {
|
|||
await item.run(element)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the status bar.
|
||||
*/
|
||||
async init (): Promise<void> {
|
||||
window.preloader.setStatus('adding plugins to statusbar...')
|
||||
|
||||
117
src/instances/WindowManager.ts
Normal file
117
src/instances/WindowManager.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
|
||||
import FlowWindow from '../structures/FlowWindow'
|
||||
import { FlowWindowConfig } from '../types'
|
||||
|
||||
class WindowManager {
|
||||
private isLauncherOpen = false
|
||||
windowArea: HTMLElement
|
||||
launcher: HTMLElement
|
||||
windows: FlowWindow[] = []
|
||||
|
||||
/**
|
||||
* Creates the window container.
|
||||
*/
|
||||
constructor () {
|
||||
this.windowArea = document.createElement('window-area')
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the highest window's z-index.
|
||||
*
|
||||
* @returns The heighest window's z-index.
|
||||
*/
|
||||
getHighestZIndex (): number {
|
||||
const indexes = this.windows.map((win: FlowWindow) => {
|
||||
return parseInt(win.element.style.zIndex)
|
||||
})
|
||||
|
||||
const max = Math.max(...indexes)
|
||||
|
||||
return max === -Infinity ? 0 : max
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a window.
|
||||
*
|
||||
* @param config The config for the window to follow.
|
||||
* @returns The created window.
|
||||
*/
|
||||
createWindow (config: FlowWindowConfig): FlowWindow {
|
||||
const win = new FlowWindow(this, config)
|
||||
this.windows.push(win)
|
||||
this.windowArea.appendChild(win.element)
|
||||
return win
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the app launcher.
|
||||
*/
|
||||
toggleLauncher (): boolean {
|
||||
if (this.isLauncherOpen) {
|
||||
this.launcher.style.opacity = '0'
|
||||
this.launcher.style.backdropFilter = 'blur(0px)'
|
||||
this.launcher.style.pointerEvents = 'none'
|
||||
} else {
|
||||
this.launcher.style.opacity = '1'
|
||||
this.launcher.style.backdropFilter = 'blur(20px)'
|
||||
this.launcher.style.pointerEvents = 'all'
|
||||
}
|
||||
|
||||
this.isLauncherOpen = !this.isLauncherOpen
|
||||
return this.isLauncherOpen
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the window manager.
|
||||
*/
|
||||
async init (): Promise<void> {
|
||||
window.preloader.setPending('window manager')
|
||||
window.preloader.setStatus('creating app launcher...')
|
||||
this.launcher = document.createElement('launcher')
|
||||
|
||||
this.launcher.innerHTML = `
|
||||
<input placeholder="Search"/>
|
||||
<apps></apps>
|
||||
`;
|
||||
|
||||
(this.launcher.querySelector('input') as HTMLInputElement).onkeyup = () => {
|
||||
(this.launcher.querySelector('apps') as HTMLElement).innerHTML = ''
|
||||
if ((this.launcher.querySelector('input') as HTMLInputElement).value !== '') {
|
||||
window.flow.apps.filter(x => x.meta.name.toLowerCase().includes((this.launcher.querySelector('input') as HTMLInputElement).value.toLowerCase())).forEach((app) => {
|
||||
const appElement = document.createElement('app')
|
||||
appElement.onclick = async () => {
|
||||
await window.flow.openApp(app.meta.pkg)
|
||||
this.toggleLauncher()
|
||||
}
|
||||
appElement.innerHTML = `<img src="${app.meta.icon}"><div>${app.meta.name}</div>`
|
||||
this.launcher.querySelector('apps')?.appendChild(appElement)
|
||||
})
|
||||
} else {
|
||||
window.flow.apps.forEach((app) => {
|
||||
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.meta.pkg)
|
||||
window.wm.toggleLauncher()
|
||||
}
|
||||
appElement.innerHTML = `<img src="${app.meta.icon}"><div>${app.meta.name}</div>`
|
||||
window.wm.launcher.querySelector('apps')?.appendChild(appElement)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.launcher.onclick = (e) => {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.toggleLauncher()
|
||||
}
|
||||
|
||||
(this.launcher.querySelector('apps') as HTMLElement).onclick = (e) => {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.toggleLauncher()
|
||||
}
|
||||
|
||||
await window.preloader.setDone('window manager')
|
||||
}
|
||||
}
|
||||
|
||||
export default WindowManager
|
||||
|
|
@ -1,6 +1,13 @@
|
|||
import { v4 as uuid } from 'uuid'
|
||||
import { FlowWindowConfig } from './types.ts'
|
||||
import WindowManager from '../instances/WindowManager'
|
||||
import { FlowWindowConfig } from '../types'
|
||||
|
||||
/**
|
||||
* Makes an element draggable.
|
||||
*
|
||||
* @param element The element to become draggable.
|
||||
* @param container The draggable element container.
|
||||
*/
|
||||
function dragElement (element: HTMLElement, container: HTMLElement): void {
|
||||
let posX = 0; let posY = 0
|
||||
|
||||
|
|
@ -53,7 +60,7 @@ function dragElement (element: HTMLElement, container: HTMLElement): void {
|
|||
}
|
||||
}
|
||||
|
||||
export class FlowWindow {
|
||||
class FlowWindow {
|
||||
element: HTMLElement
|
||||
|
||||
private readonly header: HTMLElement
|
||||
|
|
@ -69,19 +76,25 @@ export class FlowWindow {
|
|||
isMinimized = false
|
||||
isMaximized = false
|
||||
|
||||
wm: WM
|
||||
wm: WindowManager
|
||||
|
||||
id = uuid()
|
||||
|
||||
config: FlowWindowConfig
|
||||
|
||||
constructor (wm: WM, config: FlowWindowConfig) {
|
||||
/**
|
||||
* Creates a window session.
|
||||
*
|
||||
* @param wm The current window manager session.
|
||||
* @param config The window's pre-set config.
|
||||
*/
|
||||
constructor (wm: WindowManager, config: FlowWindowConfig) {
|
||||
this.wm = wm
|
||||
this.config = config
|
||||
|
||||
this.element = document.createElement('window')
|
||||
|
||||
this.element.style.zIndex = (wm.getHighestZIndex() + 1).toString()
|
||||
this.element.style.zIndex = (window.wm.getHighestZIndex() + 1).toString()
|
||||
this.element.style.position = 'absolute'
|
||||
this.focus()
|
||||
|
||||
|
|
@ -141,6 +154,11 @@ export class FlowWindow {
|
|||
dragElement(this.element, (document.querySelector('window-area') as HTMLElement))
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the window's minimization.
|
||||
*
|
||||
* @returns The window's current minimization state.
|
||||
*/
|
||||
toggleMin (): boolean {
|
||||
if (this.isMinimized) {
|
||||
this.element.style.pointerEvents = 'all'
|
||||
|
|
@ -158,6 +176,12 @@ export class FlowWindow {
|
|||
private prevLeft: string
|
||||
private prevWidth: string
|
||||
private prevHeight: string
|
||||
|
||||
/**
|
||||
* Toggles the window's maximization.
|
||||
*
|
||||
* @returns The window's current maximization state.
|
||||
*/
|
||||
toggleMax (): boolean {
|
||||
if (this.isMaximized) {
|
||||
this.element.style.width = this.prevWidth
|
||||
|
|
@ -180,113 +204,32 @@ export class FlowWindow {
|
|||
return this.isMaximized
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the window.
|
||||
*/
|
||||
focus (): void {
|
||||
if (this.element.style.zIndex !== this.wm.getHighestZIndex().toString()) {
|
||||
this.element.style.zIndex = (this.wm.getHighestZIndex() + 1).toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the window.
|
||||
*/
|
||||
close (): void {
|
||||
this.element.remove()
|
||||
const event = new CustomEvent('app_closed', { detail: { win: this } })
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of the window.
|
||||
*
|
||||
* @param title - The desired window title.
|
||||
*/
|
||||
setTitle (title: string): void {
|
||||
(this.header.querySelector('.title') as HTMLElement).innerText = title
|
||||
}
|
||||
}
|
||||
|
||||
class WM {
|
||||
private isLauncherOpen = false
|
||||
windowArea: HTMLElement
|
||||
launcher: HTMLElement
|
||||
windows: FlowWindow[] = []
|
||||
|
||||
constructor () {
|
||||
this.windowArea = document.createElement('window-area')
|
||||
}
|
||||
|
||||
getHighestZIndex (): number {
|
||||
const indexes = this.windows.map((win: FlowWindow) => {
|
||||
return parseInt(win.element.style.zIndex)
|
||||
})
|
||||
|
||||
const max = Math.max(...indexes)
|
||||
|
||||
return max === -Infinity ? 0 : max
|
||||
}
|
||||
|
||||
createWindow (config: FlowWindowConfig): FlowWindow {
|
||||
const win = new FlowWindow(this, config)
|
||||
this.windows.push(win)
|
||||
this.windowArea.appendChild(win.element)
|
||||
return win
|
||||
}
|
||||
|
||||
toggleLauncher (): boolean {
|
||||
if (this.isLauncherOpen) {
|
||||
this.launcher.style.opacity = '0'
|
||||
this.launcher.style.backdropFilter = 'blur(0px)'
|
||||
this.launcher.style.pointerEvents = 'none'
|
||||
} else {
|
||||
this.launcher.style.opacity = '1'
|
||||
this.launcher.style.backdropFilter = 'blur(20px)'
|
||||
this.launcher.style.pointerEvents = 'all'
|
||||
}
|
||||
|
||||
this.isLauncherOpen = !this.isLauncherOpen
|
||||
return this.isLauncherOpen
|
||||
}
|
||||
|
||||
async init (): Promise<void> {
|
||||
window.preloader.setPending('window manager')
|
||||
window.preloader.setStatus('creating app launcher...')
|
||||
this.launcher = document.createElement('launcher')
|
||||
|
||||
this.launcher.innerHTML = `
|
||||
<input placeholder="Search"/>
|
||||
<apps></apps>
|
||||
`;
|
||||
|
||||
(this.launcher.querySelector('input') as HTMLInputElement).onkeyup = () => {
|
||||
(this.launcher.querySelector('apps') as HTMLElement).innerHTML = ''
|
||||
if ((this.launcher.querySelector('input') as HTMLInputElement).value !== '') {
|
||||
window.flow.apps.filter(x => x.meta.name.toLowerCase().includes((this.launcher.querySelector('input') as HTMLInputElement).value.toLowerCase())).forEach((app) => {
|
||||
const appElement = document.createElement('app')
|
||||
appElement.onclick = async () => {
|
||||
await window.flow.openApp(app.meta.pkg)
|
||||
this.toggleLauncher()
|
||||
}
|
||||
appElement.innerHTML = `<img src="${app.meta.icon}"><div>${app.meta.name}</div>`
|
||||
this.launcher.querySelector('apps')?.appendChild(appElement)
|
||||
})
|
||||
} else {
|
||||
window.flow.apps.forEach((app) => {
|
||||
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.meta.pkg)
|
||||
window.wm.toggleLauncher()
|
||||
}
|
||||
appElement.innerHTML = `<img src="${app.meta.icon}"><div>${app.meta.name}</div>`
|
||||
window.wm.launcher.querySelector('apps')?.appendChild(appElement)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.launcher.onclick = (e) => {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.toggleLauncher()
|
||||
}
|
||||
|
||||
(this.launcher.querySelector('apps') as HTMLElement).onclick = (e) => {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.toggleLauncher()
|
||||
}
|
||||
|
||||
await window.preloader.setDone('window manager')
|
||||
}
|
||||
}
|
||||
|
||||
export default WM
|
||||
export default FlowWindow
|
||||
13
src/types.ts
13
src/types.ts
|
|
@ -1,10 +1,8 @@
|
|||
import { FlowWindow } from './wm'
|
||||
import FlowWindow from './structures/FlowWindow'
|
||||
|
||||
export type AppOpenFunction = (data: any) => Promise<FlowWindow>
|
||||
export type PluginRunFunction = (element: HTMLDivElement) => void | Promise<void>
|
||||
|
||||
/* EVENTS */
|
||||
|
||||
export interface AppClosedEvent extends CustomEvent {
|
||||
detail: {
|
||||
win: FlowWindow
|
||||
|
|
@ -17,9 +15,6 @@ export interface AppOpenedEvent extends CustomEvent {
|
|||
win: FlowWindow
|
||||
}
|
||||
}
|
||||
|
||||
/* METADATA */
|
||||
|
||||
export interface BaseMeta {
|
||||
name: string
|
||||
description: string
|
||||
|
|
@ -35,8 +30,6 @@ export interface PluginMeta extends BaseMeta {
|
|||
icon?: string
|
||||
}
|
||||
|
||||
/* OBJECTS */
|
||||
|
||||
export interface Apps {
|
||||
[key: string]: App
|
||||
}
|
||||
|
|
@ -45,8 +38,6 @@ export interface Plugins {
|
|||
[key: string]: Plugin
|
||||
}
|
||||
|
||||
/* MAIN INTERFACES */
|
||||
|
||||
export interface App {
|
||||
meta: AppMeta
|
||||
open: AppOpenFunction
|
||||
|
|
@ -57,8 +48,6 @@ export interface Plugin {
|
|||
run: PluginRunFunction
|
||||
}
|
||||
|
||||
/* MISC */
|
||||
|
||||
export interface FlowWindowConfig {
|
||||
title: string
|
||||
icon: string
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue