diff --git a/src/apps/editor.ts b/src/apps/editor.ts
index eacf3bc..f3643f4 100644
--- a/src/apps/editor.ts
+++ b/src/apps/editor.ts
@@ -30,8 +30,7 @@ export default class EditorApp implements App {
title: this.name,
icon,
width: 500,
- height: 400,
- canResize: true
+ height: 400
})
if (data != null) {
diff --git a/src/apps/files.ts b/src/apps/files.ts
index 5c2d5d5..6ddaa50 100644
--- a/src/apps/files.ts
+++ b/src/apps/files.ts
@@ -1,7 +1,6 @@
import icon from '../assets/icons/files.png'
import { App } from '../types.ts'
-import flow from '../flow.ts'
import { FlowWindow } from '../wm.ts'
import { Stats } from 'fs'
@@ -17,8 +16,7 @@ export default class FilesApp implements App {
title: this.name,
icon,
width: 500,
- height: 400,
- canResize: true
+ height: 400
})
win.content.style.display = 'flex'
@@ -121,7 +119,7 @@ export default class FilesApp implements App {
if (fileStat.isDirectory()) {
await setDir(dir + separator + file)
} else {
- flow.openApp('flow.editor', { path: dir + separator + file })
+ await window.flow.openApp('flow.editor', { path: dir + separator + file })
}
}
diff --git a/src/apps/info.ts b/src/apps/info.ts
index 2e69b75..00b7178 100644
--- a/src/apps/info.ts
+++ b/src/apps/info.ts
@@ -25,6 +25,7 @@ export default class SettingsApp implements App {
win.content.style.flexDirection = 'column'
win.content.style.justifyContent = 'center'
win.content.style.alignItems = 'center'
+ win.content.style.background = 'var(--base)'
win.content.innerHTML = `
FlowOS
diff --git a/src/apps/manager.ts b/src/apps/manager.ts
new file mode 100644
index 0000000..cfc064f
--- /dev/null
+++ b/src/apps/manager.ts
@@ -0,0 +1,40 @@
+import icon from '../assets/icons/manager.png'
+import { App } from '../types.ts'
+import { FlowWindow } from '../wm.ts'
+
+export default class ManagerApp implements App {
+ name = 'Manager'
+ pkg = 'flow.manager'
+ icon = icon
+ version = '1.0.0'
+
+ async open (): Promise
{
+ const win = window.wm.createWindow({
+ title: this.name,
+ icon,
+ width: 350,
+ height: 500
+ })
+
+ win.content.style.display = 'flex'
+ win.content.style.flexDirection = 'column'
+ win.content.style.gap = '10px'
+ win.content.style.padding = '10px'
+ win.content.style.background = 'var(--base)'
+ win.content.innerHTML = `
+ ${window.flow.apps.map(app => {
+ return `
+
+

+
+
${app.name} ${(app.builtin ?? false) ? '(builtin)' : ''}
+
${app.pkg} (v${app.version})
+
+
+ `
+ }).join('')}
+ `
+
+ return win
+ }
+}
diff --git a/src/apps/music.ts b/src/apps/music.ts
index f31ad2b..c7fe8f2 100644
--- a/src/apps/music.ts
+++ b/src/apps/music.ts
@@ -13,10 +13,10 @@ export default class MusicApp implements App {
title: this.name,
icon,
width: 700,
- height: 300,
- canResize: true
+ height: 300
})
+ win.content.style.background = 'var(--base)'
win.content.innerHTML = 'hi'
return win
diff --git a/src/apps/settings.ts b/src/apps/settings.ts
index 3354c83..42285c2 100644
--- a/src/apps/settings.ts
+++ b/src/apps/settings.ts
@@ -13,10 +13,10 @@ export default class SettingsApp implements App {
title: this.name,
icon,
width: 700,
- height: 300,
- canResize: true
+ height: 300
})
+ win.content.style.background = 'var(--base)'
win.content.style.padding = '10px'
win.content.innerHTML = `
Settings
diff --git a/src/assets/icons/manager.png b/src/assets/icons/manager.png
new file mode 100644
index 0000000..1a1ccfd
Binary files /dev/null and b/src/assets/icons/manager.png differ
diff --git a/src/flow.ts b/src/flow.ts
index bf53e0c..151deef 100644
--- a/src/flow.ts
+++ b/src/flow.ts
@@ -1,24 +1,67 @@
-import { Flow } from './types.ts'
+import { App, LoadedApp } from './types.ts'
-import SettingsApp from './apps/settings.ts'
-import FilesApp from './apps/files.ts'
-import MusicApp from './apps/music.ts'
-import EditorApp from './apps/editor.ts'
-import InfoApp from './apps/info.ts'
+class Flow {
+ apps: LoadedApp[] = []
+ appList = [
+ 'settings',
+ 'music',
+ 'files',
+ 'editor',
+ 'info',
+ 'manager'
+ ]
-const flow: Flow = {
- apps: {
- 'flow.settings': new SettingsApp(),
- 'flow.music': new MusicApp(),
- 'flow.files': new FilesApp(),
- 'flow.editor': new EditorApp(),
- 'flow.info': new InfoApp()
- },
- async openApp (pkg: string, data: any) {
- const win = this.apps[pkg].open(data)
- const event = new CustomEvent('app_opened', { detail: { app: this.apps[pkg], win: await win } })
+ async init (): Promise {
+ window.preloader.setPending('apps')
+ window.preloader.setStatus('importing default apps...')
+
+ for (const appPath of this.appList) {
+ const { default: ImportedApp } = await import(`./apps/${appPath}.ts`)
+ const app = new ImportedApp()
+ app.builtin = true
+
+ window.preloader.setStatus(`importing default apps\n${appPath}`)
+ this.add(app)
+ }
+
+ window.wm.launcher.style.opacity = '0'
+ window.wm.launcher.style.filter = 'blur(0px)'
+ window.wm.launcher.style.pointerEvents = 'none'
+
+ window.preloader.setStatus('adding apps to app launcher...')
+
+ this.apps.forEach((app) => {
+ window.preloader.setStatus(`adding apps to app launcher\n${app.name}`)
+ const appElement = document.createElement('app')
+ appElement.onclick = async () => {
+ await window.flow.openApp(app.pkg)
+ window.wm.toggleLauncher()
+ }
+ appElement.innerHTML = `
${app.name}
`
+ window.wm.launcher.querySelector('apps')?.appendChild(appElement)
+ })
+
+ document.body.appendChild(window.wm.windowArea)
+ document.body.appendChild(window.wm.launcher)
+
+ 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.`)
+ return
+ }
+
+ this.apps.push(app)
+ }
+
+ async openApp (pkg: string, data?: any): Promise {
+ const app = this.apps.find(x => x.pkg === pkg)
+ const win = app?.open(data)
+ const event = new CustomEvent('app_opened', { detail: { app, win: await win } })
window.dispatchEvent(event)
}
}
-export default flow
+export default Flow
diff --git a/src/index.ts b/src/index.ts
index 312bb1c..13febd1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -3,15 +3,17 @@ import './style.less'
import Preloader from './preloader'
import StatusBar from './statusbar'
import WM from './wm'
+import Flow from './flow'
import * as fs from 'fs'
declare global {
interface Window {
preloader: Preloader
+ flow: Flow
+ fs: typeof fs
statusBar: StatusBar
wm: WM
- fs: typeof fs
}
}
@@ -28,6 +30,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();
@@ -39,6 +42,8 @@ window.wm = new WM();
await window.statusBar.init()
await window.wm.init()
+ await window.flow.init()
+
window.preloader.setStatus('')
window.preloader.finish()
})().catch(e => console.error)
diff --git a/src/modules/appLauncher.ts b/src/modules/appLauncher.ts
index 14c263b..3d13dac 100644
--- a/src/modules/appLauncher.ts
+++ b/src/modules/appLauncher.ts
@@ -1,7 +1,7 @@
export const meta = {
- name: 'App View',
- description: 'Opens the app view.',
- id: 'appview'
+ name: 'App Launcher',
+ description: 'Opens the app launcher.',
+ id: 'applauncher'
}
export const run = (element: HTMLDivElement): void => {
diff --git a/src/types.ts b/src/types.ts
index f978b3b..be3293b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -44,15 +44,16 @@ export interface FlowWindowConfig {
width?: number
height?: number
- canResize: boolean
+ canResize?: boolean
minWidth?: number
minHeight?: number
}
-export interface Flow {
- apps: {
- [key: string]: App
- }
- openApp: Function
+export interface Apps {
+ [key: string]: App
+}
+
+export interface LoadedApp extends App {
+ builtin: boolean
}
diff --git a/src/wm.ts b/src/wm.ts
index 82b6d40..4119596 100644
--- a/src/wm.ts
+++ b/src/wm.ts
@@ -1,4 +1,3 @@
-import flow from './flow.ts'
import { v4 as uuid } from 'uuid'
import { FlowWindowConfig } from './types.ts'
@@ -89,12 +88,14 @@ export class FlowWindow {
this.focus()
}
+ if (config.canResize === undefined) config.canResize = true
+
this.element.style.width = `${config.width ?? 300}px`
this.element.style.height = `${config.height ?? 200}px`
this.header = document.createElement('window-header')
this.header.innerHTML = `
${config.title}
`
- if (config.canResize) {
+ if (!config.canResize) {
this.header.innerHTML = `
${config.title}
`
}
@@ -104,7 +105,7 @@ export class FlowWindow {
(this.header.querySelector('#min') as HTMLElement).onclick = () => this.toggleMin()
- if (config.canResize) {
+ if (!config.canResize) {
(this.header.querySelector('#max') as HTMLElement).onclick = () => this.toggleMax()
}
@@ -234,26 +235,6 @@ class WM {
this.toggleLauncher()
}
- this.launcher.style.opacity = '0'
- this.launcher.style.filter = 'blur(0px)'
- this.launcher.style.pointerEvents = 'none'
-
- window.preloader.setStatus('adding apps to app launcher...')
-
- for (const pkg in flow.apps) {
- window.preloader.setStatus(`adding apps to app launcher\n${flow.apps[pkg].name}`)
- const app = document.createElement('app')
- app.onclick = () => {
- flow.openApp(pkg)
- this.toggleLauncher()
- }
- app.innerHTML = `
${flow.apps[pkg].name}
`
- this.launcher.querySelector('apps')?.appendChild(app)
- }
-
- document.body.appendChild(this.windowArea)
- document.body.appendChild(this.launcher)
-
await window.preloader.setDone('window manager')
}
}