diff --git a/eslint.config.js b/eslint.config.js index 8ab6996..4dd7f07 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -4,6 +4,7 @@ import eslint from "@eslint/js"; import tseslint from "typescript-eslint"; import react from "eslint-plugin-react"; import reactRefresh from "eslint-plugin-react-refresh"; +import * as pluginImport from "eslint-plugin-import"; export default tseslint.config( eslint.configs.recommended, @@ -22,6 +23,9 @@ export default tseslint.config( plugins: { react, "react-refresh": reactRefresh, + import: { + rules: pluginImport.rules + } }, rules: { "quotes": "off", @@ -66,6 +70,7 @@ export default tseslint.config( "warn", { "allowConstantExport": true } ], + "import/no-relative-packages": "error" }, } ); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 15539ca..fe1f845 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", "@prozilla-os/core": "^1.0.0", + "@prozilla-os/file-explorer": "^1.0.0", "@vitejs/plugin-react-swc": "^3.7.0", "anser": "^2.1.1", "escape-carriage": "^1.3.1", @@ -42,6 +43,7 @@ "@types/react-dom": "^18.3.0", "@types/react-syntax-highlighter": "^15.5.13", "eslint": "^8.57.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-refresh": "^0.4.7", "gh-pages": "^5.0.0", @@ -1769,6 +1771,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -2238,6 +2246,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", @@ -3237,6 +3265,113 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-react": { "version": "7.34.1", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", @@ -5140,6 +5275,15 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minimist-options": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", @@ -5312,6 +5456,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.hasown": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", @@ -6163,8 +6321,6 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -6662,6 +6818,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -7006,6 +7171,30 @@ "typescript": ">=4.2.0" } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", diff --git a/package.json b/package.json index 783ea2d..94f6c93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@prozilla-os/prozilla-os", "version": "0.1.0", + "private": true, "author": { "name": "Prozilla", "email": "business@prozilla.dev", @@ -8,10 +9,6 @@ }, "homepage": "https://os.prozilla.dev/", "repository": "https://github.com/Prozilla/ProzillaOS", - "workspaces": [ - "packages/core", - "packages/apps/file-explorer" - ], "type": "module", "scripts": { "start": "vite", @@ -22,12 +19,17 @@ "deploy": "tsx scripts/deploy", "fetch": "tsx scripts/fetchRepository" }, + "workspaces": [ + "packages/core", + "packages/apps/file-explorer" + ], "dependencies": { + "@prozilla-os/core": "^1.0.0", + "@prozilla-os/file-explorer": "^1.0.0", "@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/free-regular-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", - "@prozilla-os/core": "^1.0.0", "@vitejs/plugin-react-swc": "^3.7.0", "anser": "^2.1.1", "escape-carriage": "^1.3.1", @@ -53,6 +55,7 @@ "@types/react-dom": "^18.3.0", "@types/react-syntax-highlighter": "^15.5.13", "eslint": "^8.57.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-refresh": "^0.4.7", "gh-pages": "^5.0.0", diff --git a/packages/apps/file-explorer/README.md b/packages/apps/file-explorer/README.md index dbe82f7..bc62f91 100644 --- a/packages/apps/file-explorer/README.md +++ b/packages/apps/file-explorer/README.md @@ -1 +1 @@ -# @ProzillaOS/file-explorer \ No newline at end of file +# @prozilla-os/file-explorer \ No newline at end of file diff --git a/packages/apps/file-explorer/package.json b/packages/apps/file-explorer/package.json index efc91a0..893b88b 100644 --- a/packages/apps/file-explorer/package.json +++ b/packages/apps/file-explorer/package.json @@ -11,7 +11,11 @@ "scripts": { "test": "tsc --watch" }, - "repository": "https://github.com/Prozilla/ProzillaOS", + "repository": { + "type": "git", + "url": "git+https://github.com/Prozilla/ProzillaOS.git", + "directory": "packages/apps/file-explorer" + }, "license": "MIT", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.5.2", diff --git a/packages/apps/file-explorer/src/components/FileExplorer.tsx b/packages/apps/file-explorer/src/components/FileExplorer.tsx index 7067ce7..2a4b225 100644 --- a/packages/apps/file-explorer/src/components/FileExplorer.tsx +++ b/packages/apps/file-explorer/src/components/FileExplorer.tsx @@ -4,11 +4,11 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faArrowUp, faCaretLeft, faCaretRight, faCircleInfo, faCog, faDesktop, faFileLines, faHouse, faImage, faPlus, faSearch, faTrash } from "@fortawesome/free-solid-svg-icons"; import { QuickAccessButton } from "./QuickAccessButton"; import { ImportButton } from "./ImportButton"; -import { Actions, AppsManager, ClickAction, CODE_EXTENSIONS, DIALOG_CONTENT_TYPES, DialogBox, DirectoryList, Divider, FileEventHandler, FolderEventHandler, OnSelectionChangeParams, useAlert, useContextMenu, useHistory, useSystemManager, useVirtualRoot, useWindowedModal, useWindowsManager, utilStyles, Vector2, VirtualFile, VirtualFolder, VirtualFolderLink, VirtualRoot, WindowProps } from "@prozilla-os/core"; +import { Actions, ClickAction, CODE_EXTENSIONS, DIALOG_CONTENT_TYPES, DialogBox, DirectoryList, Divider, FileEventHandler, FolderEventHandler, OnSelectionChangeParams, useAlert, useContextMenu, useHistory, useSystemManager, useVirtualRoot, useWindowedModal, useWindowsManager, utilStyles, Vector2, VirtualFile, VirtualFolder, VirtualFolderLink, VirtualRoot, WindowProps } from "@prozilla-os/core"; import { SELECTOR_MODE } from "../constants/fileExplorer.const"; import { FileProperties } from "./modals/file-properties/FileProperties"; -interface FileExplorerProps extends WindowProps { +export interface FileExplorerProps extends WindowProps { path?: string; selectorMode?: number; Footer: FC; @@ -109,7 +109,7 @@ export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSel alert({ title: (error as Error).message, text: "You have exceeded the virtual drive capacity. Files and folders will not be saved until more storage is freed.", - iconUrl: app?.id != null ? AppsManager.getAppIconUrl(app.id) : undefined, + iconUrl: app?.iconUrl as string | undefined, size: new Vector2(300, 200), single: true, }); @@ -138,7 +138,7 @@ export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSel if (directory == null) { openWindowedModal({ title: "Error", - iconUrl: app?.id != null ? AppsManager.getAppIconUrl(app.id) : undefined, + iconUrl: app?.iconUrl as string | undefined, size: new Vector2(300, 150), Modal: (props: {}) => diff --git a/packages/apps/file-explorer/src/components/modals/file-properties/FileProperties.tsx b/packages/apps/file-explorer/src/components/modals/file-properties/FileProperties.tsx index 1d76616..fe23af6 100644 --- a/packages/apps/file-explorer/src/components/modals/file-properties/FileProperties.tsx +++ b/packages/apps/file-explorer/src/components/modals/file-properties/FileProperties.tsx @@ -1,13 +1,13 @@ import styles from "./FileProperties.module.css"; -import utilStyles from "../../../styles/utils.module.css"; -import { AppsManager, ImagePreview, ModalProps, StorageManager, VirtualFile, WindowedModal } from "@prozilla-os/core"; +import { ImagePreview, ModalProps, StorageManager, useSystemManager, utilStyles, VirtualFile, WindowedModal } from "@prozilla-os/core"; interface FilePropetiesProps extends ModalProps { file: VirtualFile; } export function FileProperties({ modal, params, file, ...props }: FilePropetiesProps) { - const associatedApp = file.extension != null ? AppsManager.getAppByFileExtension(file.extension) : null; + const { appsConfig } = useSystemManager(); + const associatedApp = file.extension != null ? appsConfig.getAppByFileExtension(file.extension) : null; return @@ -19,7 +19,7 @@ export function FileProperties({ modal, params, file, ...props }: FilePropetiesP {associatedApp != null && Opens with: - + {associatedApp.name} } diff --git a/packages/apps/file-explorer/src/index.ts b/packages/apps/file-explorer/src/index.ts index 95c8fe9..1bcfaca 100644 --- a/packages/apps/file-explorer/src/index.ts +++ b/packages/apps/file-explorer/src/index.ts @@ -1,2 +1,10 @@ -export { SELECTOR_MODE } from "./constants/fileExplorer.const"; -export { FileExplorer } from "./components/FileExplorer"; \ No newline at end of file +import { App } from "@prozilla-os/core"; +import { FileExplorer } from "./components/FileExplorer"; +import { VirtualBase } from "@prozilla-os/core/src/features/virtual-drive/virtualBase"; + +const fileExplorer = new App("File Explorer", "file-explorer", FileExplorer) + .setIconUrl("https://os.prozilla.dev/assets/apps/icons/file-explorer.svg"); + +export { fileExplorer }; +export { FileSelectorMode } from "./types/index.d"; +VirtualBase; \ No newline at end of file diff --git a/packages/apps/file-explorer/src/types/index.d.ts b/packages/apps/file-explorer/src/types/index.d.ts new file mode 100644 index 0000000..a4a292b --- /dev/null +++ b/packages/apps/file-explorer/src/types/index.d.ts @@ -0,0 +1,5 @@ +export enum FileSelectorMode { + None = 0, + Single = 1, + Multi = 2 +} \ No newline at end of file diff --git a/packages/core/README.md b/packages/core/README.md index aa3cf87..b1099d1 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1 +1 @@ -# @ProzillaOS/core \ No newline at end of file +# @prozilla-os/core \ No newline at end of file diff --git a/packages/core/package.json b/packages/core/package.json index d7d1bcc..d17def8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -11,9 +11,14 @@ "scripts": { "test": "tsc --watch" }, - "repository": "https://github.com/Prozilla/ProzillaOS", + "repository": { + "type": "git", + "url": "git+https://github.com/Prozilla/ProzillaOS.git", + "directory": "packages/core" + }, "license": "MIT", "dependencies": { + "@prozilla-os/file-explorer": "^1.0.0", "@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.5.2", "@fortawesome/free-solid-svg-icons": "^6.5.2", @@ -22,8 +27,7 @@ "react-draggable": "^4.4.6", "react-error-boundary": "^4.0.13", "react-ga4": "^2.1.0", - "react-svg": "^16.1.34", - "@prozilla-os/file-explorer": "^1.0.0" + "react-svg": "^16.1.34" }, "devDependencies": { "@types/node": "^20.14.2", @@ -31,5 +35,9 @@ }, "files": [ "src/index.ts" - ] + ], + "publishConfig": { + "registry": "https://npm.pkg.github.com", + "access": "public" + } } diff --git a/packages/core/src/components/_utils/directory-list/ImagePreview.tsx b/packages/core/src/components/_utils/directory-list/ImagePreview.tsx index b737568..3045f0d 100644 --- a/packages/core/src/components/_utils/directory-list/ImagePreview.tsx +++ b/packages/core/src/components/_utils/directory-list/ImagePreview.tsx @@ -1,8 +1,7 @@ import { useState } from "react"; import styles from "./ImagePreview.module.css"; import { ReactSVG } from "react-svg"; -import { AppsManager } from "../../../features"; -import { APPS } from "../../../constants/apps.const"; +import { useSystemManager } from "../../../hooks"; interface ImagePreviewProps { source: string; @@ -11,6 +10,7 @@ interface ImagePreviewProps { } export function ImagePreview({ source, className, onError, ...props }: ImagePreviewProps) { + const { virtualDriveConfig } = useSystemManager(); const [loadingFailed, setLoadingFailed] = useState(false); const onLoadingError = () => { @@ -24,7 +24,7 @@ export function ImagePreview({ source, className, onError, ...props }: ImagePrev return (
{loadingFailed - ? + ? : source.endsWith(".svg") ? : Preview diff --git a/packages/core/src/components/_utils/interactable/Interactable.tsx b/packages/core/src/components/_utils/interactable/Interactable.tsx index 04b3943..ac0c74b 100644 --- a/packages/core/src/components/_utils/interactable/Interactable.tsx +++ b/packages/core/src/components/_utils/interactable/Interactable.tsx @@ -31,7 +31,7 @@ export function Interactable({ onClick, onDoubleClick, children, ...props }: Int setClicked(true); onClick?.(event); - timeoutId = setTimeout(() => { + timeoutId = window.setTimeout(() => { setClicked(false); }, miscConfig.doubleClickDelay); }; diff --git a/packages/core/src/components/desktop/Desktop.tsx b/packages/core/src/components/desktop/Desktop.tsx index 36c2900..171cead 100644 --- a/packages/core/src/components/desktop/Desktop.tsx +++ b/packages/core/src/components/desktop/Desktop.tsx @@ -10,13 +10,13 @@ import { RadioAction } from "../actions/actions/RadioAction"; import { Divider } from "../actions/actions/Divider"; import { Share } from "../modals/share/Share"; import { ModalProps } from "../modals/ModalView"; -import { APP_NAMES, APP_ICONS, APPS } from "../../constants/apps.const"; import { SettingsManager, reloadViewport, ModalsManager, Vector2, isValidInteger } from "../../features"; import { VirtualFile } from "../../features/virtual-drive/file"; import { VirtualFolder, VirtualFolderLink } from "../../features/virtual-drive/folder"; import { useSettingsManager, useWindowsManager, useVirtualRoot, useWindowedModal, useContextMenu, useSystemManager } from "../../hooks"; import { DirectoryList } from "../_utils"; import { FileEventHandler, FolderEventHandler } from "../_utils/directory-list/DirectoryList"; +import { fileExplorer } from "@prozilla-os/file-explorer"; export const Desktop = memo(() => { const { desktopConfig } = useSystemManager(); @@ -83,12 +83,12 @@ export const Desktop = memo(() => { windowsManager?.open("settings", { tab: 2 }); }}/> - { - windowsManager?.open(APPS.FILE_EXPLORER, { path: directory?.path }); + { + windowsManager?.open(fileExplorer.id, { path: directory?.path }); }}/> - { + {/* { windowsManager?.open(APPS.TERMINAL, { path: directory?.path }); - }}/> + }}/> */} { openWindowedModal({ @@ -103,7 +103,7 @@ export const Desktop = memo(() => { { if (windowsManager != null) (file as VirtualFile).open(windowsManager); }}/> - { + { if (windowsManager != null) (file as VirtualFile).parent?.open(windowsManager); }}/> { @@ -116,10 +116,10 @@ export const Desktop = memo(() => { { if (windowsManager != null) (folder as VirtualFolder).open(windowsManager); }}/> - { + {/* { windowsManager?.open(APPS.TERMINAL, { path: (folder as VirtualFolder).path }); - }}/> - { + }}/> */} + { if (windowsManager != null) (folder as VirtualFolder).parent?.open(windowsManager); }}/> @@ -183,7 +183,7 @@ export const Desktop = memo(() => { windowsManager?.openFile(file, options); }} onOpenFolder={(event, folder) => { - windowsManager?.open(APPS.FILE_EXPLORER, { + windowsManager?.open(fileExplorer.id, { path: (folder as VirtualFolderLink).linkedPath ?? folder.path }); }} diff --git a/packages/core/src/components/modals/file-selector/FileSelector.tsx b/packages/core/src/components/modals/file-selector/FileSelector.tsx index 49988b1..679d654 100644 --- a/packages/core/src/components/modals/file-selector/FileSelector.tsx +++ b/packages/core/src/components/modals/file-selector/FileSelector.tsx @@ -3,19 +3,18 @@ import { Button } from "../../_utils/button/Button"; import { WindowedModal } from "../_utils/WindowedModal"; import styles from "./FileSelector.module.css"; import { ModalProps } from "../ModalView"; -import { APP_ICONS } from "../../../constants/apps.const"; import { VirtualFile } from "../../../features/virtual-drive/file"; import { VirtualFolder } from "../../../features/virtual-drive/folder"; -import { FileExplorer, SELECTOR_MODE } from "@prozilla-os/file-explorer"; +import { FileSelectorMode, fileExplorer } from "@prozilla-os/file-explorer"; interface FileSelectorProps extends ModalProps { - type: number; + type: FileSelectorMode; allowedFormats?: string[]; onFinish: (result: VirtualFile | VirtualFile[]) => void; } export function FileSelector({ modal, params, type, allowedFormats, onFinish, ...props }: FileSelectorProps) { - const multi = (type === SELECTOR_MODE.MULTIPLE); + const multi = (type == FileSelectorMode.Multi); const [selection, setSelection] = useState(multi ? [] : null); const [directory, setDirectory] = useState(null); @@ -45,10 +44,10 @@ export function FileSelector({ modal, params, type, allowedFormats, onFinish, .. return -
diff --git a/packages/core/src/components/modals/share/Share.tsx b/packages/core/src/components/modals/share/Share.tsx index 5e627e0..0991a02 100644 --- a/packages/core/src/components/modals/share/Share.tsx +++ b/packages/core/src/components/modals/share/Share.tsx @@ -3,7 +3,6 @@ import { ModalsManager } from "../../../features/modals/modalsManager"; import { WindowedModal } from "../_utils/WindowedModal"; import styles from "./Share.module.css"; import { copyToClipboard, generateUrl } from "../../../features/_utils/browser.utils"; -import { AppsManager } from "../../../features/apps/appsManager"; import utilStyles from "../../../styles/utils.module.css"; import { Button } from "../../_utils/button/Button"; import { Option } from "./Option"; @@ -13,6 +12,7 @@ import { faSquareCheck } from "@fortawesome/free-solid-svg-icons"; import { useAlert } from "../../../hooks/modals/alert"; import { ModalProps } from "../ModalView"; import { useScrollWithShadow } from "../../../hooks/_utils/scrollWithShadows"; +import { useSystemManager } from "../../../hooks"; const APP_OPTIONS: Record = { "terminal": [ @@ -46,6 +46,7 @@ const APP_OPTIONS: Record = { }; export function Share({ modal, params, ...props }: ModalProps) { + const { appsConfig } = useSystemManager(); const [appId, setAppId] = useState(params?.appId ?? ""); const [fullscreen, setFullscreen] = useState(params?.fullscreen ?? false); const [standalone, setStandalone] = useState(params?.standalone ?? false); @@ -123,7 +124,7 @@ export function Share({ modal, params, ...props }: ModalProps) {

App:

diff --git a/packages/core/src/components/prozilla-os/ProzillaOS.tsx b/packages/core/src/components/prozilla-os/ProzillaOS.tsx index aedfccc..48e9e2f 100644 --- a/packages/core/src/components/prozilla-os/ProzillaOS.tsx +++ b/packages/core/src/components/prozilla-os/ProzillaOS.tsx @@ -15,8 +15,9 @@ import { ModalsConfig, ModalsConfigOptions } from "../../features/system/configs import { TaskbarConfig, TaskbarConfigOptions } from "../../features/system/configs/taskbarConfig"; import { TrackingConfig, TrackingConfigOptions } from "../../features/system/configs/trackingConfig"; import { WindowsConfig, WindowsConfigOptions } from "../../features/system/configs/windowsConfig"; -import { OptionalInterface } from "../../types/global"; +import { OptionalInterface } from "../../types/util"; import { TrackingManagerProvider } from "../../hooks/tracking/trackingManagerProvider"; +import { VirtualDriveConfig, VirtualDriveConfigOptions } from "../../features/system/configs/virtualDriveConfig"; interface ProzillaOSProps { systemName?: string; @@ -29,6 +30,7 @@ interface ProzillaOSProps { taskbar?: OptionalInterface; tracking?: OptionalInterface; windows?: OptionalInterface; + virtualDrive?: OptionalInterface; } children?: ReactNode; } @@ -45,7 +47,8 @@ export const ProzillaOS = memo(function(props: ProzillaOSProps): ReactElement { modalsConfig: new ModalsConfig(config?.modals), taskbarConfig: new TaskbarConfig(config?.taskbar), trackingConfig: new TrackingConfig(config?.tracking), - windowsConfig: new WindowsConfig(config?.windows) + windowsConfig: new WindowsConfig(config?.windows), + virtualDriveConfig: new VirtualDriveConfig(config?.virtualDrive), } as SystemManagerParams; return diff --git a/packages/core/src/components/taskbar/Taskbar.tsx b/packages/core/src/components/taskbar/Taskbar.tsx index ab16b9a..f267cd2 100644 --- a/packages/core/src/components/taskbar/Taskbar.tsx +++ b/packages/core/src/components/taskbar/Taskbar.tsx @@ -2,7 +2,6 @@ import { CSSProperties, memo, MouseEvent, MutableRefObject, ReactEventHandler, U import styles from "./Taskbar.module.css"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCog, faSearch } from "@fortawesome/free-solid-svg-icons"; -import { AppsManager } from "../../features/apps/appsManager"; import { ReactSVG } from "react-svg"; import { HomeMenu } from "./menus/HomeMenu"; import { OutsideClickListener } from "../../hooks/_utils/outsideClick"; @@ -12,19 +11,18 @@ import { AppButton } from "./app-icon/AppIcon"; import { useContextMenu } from "../../hooks/modals/contextMenu"; import { Actions } from "../actions/Actions"; import { ClickAction } from "../actions/actions/ClickAction"; -import { APPS, APP_NAMES } from "../../constants/apps.const"; import { useWindowsManager } from "../../hooks/windows/windowsManagerContext"; import { useSettingsManager } from "../../hooks/settings/settingsManagerContext"; import { SettingsManager } from "../../features/settings/settingsManager"; import { useWindows } from "../../hooks/windows/windowsContext"; import { ZIndexManager } from "../../features/z-index/zIndexManager"; import { useZIndex } from "../../hooks/z-index/zIndex"; -import { App } from "../../features/apps/app"; import { Battery, Calendar, Network, Volume } from "./indicators"; import { useSystemManager } from "../../hooks"; +import { App } from "../../features"; export const Taskbar = memo(() => { - const { taskbarConfig } = useSystemManager(); + const { taskbarConfig, appsConfig } = useSystemManager(); const ref = useRef(null); const settingsManager = useSettingsManager(); const [showHome, setShowHome] = useState(false); @@ -42,8 +40,8 @@ export const Taskbar = memo(() => { const windows = useWindows(); const { onContextMenu } = useContextMenu({ Actions: (props) => - { - windowsManager?.open(APPS.SETTINGS); + { + windowsManager?.open("settings"); }}/> }); @@ -55,7 +53,7 @@ export const Taskbar = memo(() => { void settings?.get("pins", (pinList: string) => { const pins = pinList.split(","); - const newApps = AppsManager.APPS.sort((appA, appB) => { + const newApps = appsConfig.apps.sort((appA, appB) => { const indexA = pins.indexOf(appA.id); const indexB = pins.indexOf(appB.id); if (indexA < 0 && indexB > 0) { diff --git a/packages/core/src/components/taskbar/app-icon/AppIcon.tsx b/packages/core/src/components/taskbar/app-icon/AppIcon.tsx index a4826a7..b473723 100644 --- a/packages/core/src/components/taskbar/app-icon/AppIcon.tsx +++ b/packages/core/src/components/taskbar/app-icon/AppIcon.tsx @@ -1,12 +1,11 @@ import { FC, memo, MouseEvent } from "react"; -import { App } from "../../../features/apps/app"; +import { App } from "../../../features/system/configs/app"; import styles from "./AppIcon.module.css"; import { ReactSVG } from "react-svg"; import { useSettingsManager } from "../../../hooks/settings/settingsManagerContext"; import { useContextMenu } from "../../../hooks/modals/contextMenu"; import { Actions } from "../../actions/Actions"; import { ClickAction } from "../../actions/actions/ClickAction"; -import { AppsManager } from "../../../features/apps/appsManager"; import { WindowsManager } from "../../../features/windows/windowsManager"; interface AppButtonProps { @@ -20,7 +19,7 @@ export const AppButton: FC = memo(({ app, windowsManager, active const settingsManager = useSettingsManager(); const { onContextMenu } = useContextMenu({ Actions: (props) => - { + { windowsManager?.open(app.id); }}/> {/* { diff --git a/packages/core/src/components/taskbar/menus/HomeMenu.tsx b/packages/core/src/components/taskbar/menus/HomeMenu.tsx index 501c07b..8ab5d1d 100644 --- a/packages/core/src/components/taskbar/menus/HomeMenu.tsx +++ b/packages/core/src/components/taskbar/menus/HomeMenu.tsx @@ -6,9 +6,9 @@ import { faCircleInfo, faFileLines, faGear, faImage, faPowerOff } from "@fortawe import { ReactSVG } from "react-svg"; import { useEffect, useState } from "react"; import { utilStyles } from "../../.."; -import { APPS } from "../../../constants/apps.const"; -import { closeViewport, Vector2, AppsManager } from "../../../features"; +import { closeViewport, Vector2 } from "../../../features"; import { useWindowsManager, useVirtualRoot, useKeyboardListener, useSystemManager } from "../../../hooks"; +import { fileExplorer } from "@prozilla-os/file-explorer"; interface HomeMenuProps { active: boolean; @@ -17,7 +17,7 @@ interface HomeMenuProps { } export function HomeMenu({ active, setActive, search }: HomeMenuProps) { - const { systemName } = useSystemManager(); + const { systemName, appsConfig } = useSystemManager(); const windowsManager = useWindowsManager(); const virtualRoot = useVirtualRoot(); const [tabIndex, setTabIndex] = useState(active ? 0 : -1); @@ -81,13 +81,13 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) { @@ -95,7 +95,7 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) {

{systemName}

- {AppsManager.APPS.sort((a, b) => a.name.localeCompare(b.name)).map(({ name, id }) => + {appsConfig.apps.sort((a, b) => a.name.localeCompare(b.name)).map(({ name, id, iconUrl }) => )} diff --git a/packages/core/src/components/taskbar/menus/SearchMenu.tsx b/packages/core/src/components/taskbar/menus/SearchMenu.tsx index 7512a1e..74f8ce4 100644 --- a/packages/core/src/components/taskbar/menus/SearchMenu.tsx +++ b/packages/core/src/components/taskbar/menus/SearchMenu.tsx @@ -1,11 +1,11 @@ import styles from "./SearchMenu.module.css"; import appStyles from "./AppList.module.css"; -import { AppsManager } from "../../../features/apps/appsManager"; import { useWindowsManager } from "../../../hooks/windows/windowsManagerContext"; import { ChangeEventHandler, MutableRefObject, useEffect, useState } from "react"; import { useKeyboardListener } from "../../../hooks/_utils/keyboard"; -import { App } from "../../../features/apps/app"; +import { App } from "../../../features/system/configs/app"; import { ReactSVG } from "react-svg"; +import { useSystemManager } from "../../../hooks"; interface SearchMenuProps { active: boolean; @@ -16,6 +16,7 @@ interface SearchMenuProps { } export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inputRef }: SearchMenuProps) { + const { appsConfig } = useSystemManager(); const windowsManager = useWindowsManager(); const [apps, setApps] = useState(null); const [tabIndex, setTabIndex] = useState(active ? 0 : -1); @@ -32,7 +33,7 @@ export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inp }, [inputRef]); useEffect(() => { - setApps(AppsManager.APPS.filter(({ name, id }) => + setApps(appsConfig.apps.filter(({ name, id }) => name.toLowerCase().includes(searchQuery.toLowerCase().trim()) || id.toLowerCase().includes(searchQuery.toLowerCase().trim()) ).sort((a, b) => @@ -79,7 +80,7 @@ export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inp windowsManager?.open(id); }} > - +

{name}

)} diff --git a/packages/core/src/components/windows/WindowFallbackView.tsx b/packages/core/src/components/windows/WindowFallbackView.tsx index 62134b7..434b8fb 100644 --- a/packages/core/src/components/windows/WindowFallbackView.tsx +++ b/packages/core/src/components/windows/WindowFallbackView.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from "react"; import { useAlert } from "../../hooks/modals/alert"; -import { AppsManager } from "../../features/apps/appsManager"; import { Vector2 } from "../../features/math/vector2"; -import { App } from "../../features/apps/app"; +import { App } from "../../features/system/configs/app"; +import { useSystemManager } from "../../hooks"; export interface WindowFallbackViewProps { error?: Error; @@ -13,6 +13,7 @@ export interface WindowFallbackViewProps { // I don't know why this component's type needs to be ReactNode instead of FC, it has something to do with the way it's implemented export function WindowFallbackView({ error, resetErrorBoundary: _resetErrorBoundary, app, closeWindow }: WindowFallbackViewProps): undefined { + const { appsConfig } = useSystemManager(); const { alert } = useAlert(); const [alerted, setAlerted] = useState(false); @@ -27,7 +28,7 @@ export function WindowFallbackView({ error, resetErrorBoundary: _resetErrorBound alert({ title: `${app.name} has stopped working`, text: `${error.name}: ${error.message}`, - iconUrl: AppsManager.getAppIconUrl(app.id), + iconUrl: appsConfig.getAppById(app.id)?.iconUrl as string | undefined, size: new Vector2(350, 150), single: true }); diff --git a/packages/core/src/components/windows/WindowView.tsx b/packages/core/src/components/windows/WindowView.tsx index 667c09c..57a4c4a 100644 --- a/packages/core/src/components/windows/WindowView.tsx +++ b/packages/core/src/components/windows/WindowView.tsx @@ -9,7 +9,6 @@ import { Vector2 } from "../../features/math/vector2"; import { faWindowMaximize } from "@fortawesome/free-regular-svg-icons"; import utilStyles from "../../styles/utils.module.css"; import { useContextMenu } from "../../hooks/modals/contextMenu"; -import { AppsManager } from "../../features/apps/appsManager"; import { ClickAction } from "../actions/actions/ClickAction"; import { Actions } from "../actions/Actions"; import { useScreenDimensions } from "../../hooks/_utils/screen"; @@ -41,7 +40,7 @@ export interface WindowProps extends WindowOptions { } export const WindowView: FC = memo(({ id, app, size, position, onInteract, options, active, fullscreen, minimized, toggleMinimized, index }) => { - const { systemName, windowsConfig } = useSystemManager(); + const { systemName, windowsConfig, appsConfig } = useSystemManager(); const windowsManager = useWindowsManager(); const nodeRef = useRef(null); const { openWindowedModal } = useWindowedModal(); @@ -50,7 +49,7 @@ export const WindowView: FC = memo(({ id, app, size, position, onIn const [maximized, setMaximized] = useState(fullscreen ?? false); const [screenWidth, screenHeight] = useScreenDimensions(); const [title, setTitle] = useState(app?.name ?? ""); - const [iconUrl, setIconUrl] = useState(app ? AppsManager.getAppIconUrl(app?.id) : ""); + const [iconUrl, setIconUrl] = useState(app ? appsConfig.getAppById(app?.id)?.iconUrl ?? "" : ""); const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.WINDOWS, index: index ?? 0 }); const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) => diff --git a/packages/core/src/constants/apps.const.ts b/packages/core/src/constants/apps.const.ts deleted file mode 100644 index fe1bd24..0000000 --- a/packages/core/src/constants/apps.const.ts +++ /dev/null @@ -1,43 +0,0 @@ -export const APPS = { - TERMINAL: "terminal", - SETTINGS: "settings", - MEDIA_VIEWER: "media-viewer", - TEXT_EDITOR: "text-editor", - FILE_EXPLORER: "file-explorer", - CALCULATOR: "calculator", - BROWSER: "browser", - LOGIC_SIM: "logic-sim", -}; - -export type AppKey = keyof typeof APPS; - -export const APP_NAMES: Record = { - TERMINAL: "Commands", - SETTINGS: "Settings", - MEDIA_VIEWER: "Photos", - TEXT_EDITOR: "Notes", - FILE_EXPLORER: "Files", - CALCULATOR: "Maths", - BROWSER: "Browser", - LOGIC_SIM: "Logic Sim (WIP)" -}; - -export const APP_DESCRIPTIONS: Record = { - TERMINAL: "A command line tool inspired by the Unix shell that runs entirely in your browser and uses a virtual file system.", - SETTINGS: "Configure ProzillaOS' settings and customize your experience.", - TEXT_EDITOR: "Simple text editor for reading and writing text documents.", - FILE_EXPLORER: "Browse and manage your virtual files.", - CALCULATOR: "Simple calculator app.", - BROWSER: "Browse the internet.", - LOGIC_SIM: "Create digital logic circuits using the online simulator.", - MEDIA_VIEWER: null, -}; - -export const APP_ICONS = { - TERMINAL: `/assets/apps/icons/${APPS.TERMINAL}.svg`, - SETTINGS: `/assets/apps/icons/${APPS.SETTINGS}.svg`, - MEDIA_VIEWER: `/assets/apps/icons/${APPS.MEDIA_VIEWER}.svg`, - TEXT_EDITOR: `/assets/apps/icons/${APPS.TEXT_EDITOR}.svg`, - FILE_EXPLORER: `/assets/apps/icons/${APPS.FILE_EXPLORER}.svg`, - CALCULATOR: `/assets/apps/icons/${APPS.CALCULATOR}.svg`, -}; \ No newline at end of file diff --git a/packages/core/src/constants/index.ts b/packages/core/src/constants/index.ts new file mode 100644 index 0000000..5418b12 --- /dev/null +++ b/packages/core/src/constants/index.ts @@ -0,0 +1,3 @@ +export { DIALOG_CONTENT_TYPES } from "./modals.const"; +export { CODE_EXTENSIONS } from "./virtualDrive.const"; +export { ANSI } from "./utils.const"; \ No newline at end of file diff --git a/packages/core/src/constants/utils.const.ts b/packages/core/src/constants/utils.const.ts new file mode 100644 index 0000000..c3c955c --- /dev/null +++ b/packages/core/src/constants/utils.const.ts @@ -0,0 +1,19 @@ +export const ANSI = { + fg: { + black: "\u001b[30m", + red: "\u001b[31m", + green: "\u001b[32m", + yellow: "\u001b[33m", + blue: "\u001b[34m", + magenta: "\u001b[35m", + cyan: "\u001b[36m", + white: "\u001b[37m", + }, + bg: { + + }, + decoration: { + dim: "\u001b[2m", + }, + reset: "\u001b[0m", +}; \ No newline at end of file diff --git a/packages/core/src/features/apps/app.tsx b/packages/core/src/features/apps/app.tsx deleted file mode 100644 index d11d85b..0000000 --- a/packages/core/src/features/apps/app.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Vector2 } from "../math/vector2"; -import { WindowProps } from "../../components/windows/WindowView"; -import { FC } from "react"; - -export class App { - name: string = "App"; - id: string = "app"; - windowContent?: FC; - windowOptions?: { - size: Vector2; - [key: string]: unknown; - }; - isActive: boolean = false; - isPinned?: boolean; - - /** - * @param windowOptions - Default window options - */ - constructor(name: App["name"], id: App["id"], windowContent: App["windowContent"], windowOptions?: App["windowOptions"]) { - Object.assign(this, { name, id, windowContent, windowOptions }); - - if (this.windowContent == null) - console.warn(`${this.name} (${this.id}) is missing the windowContent property.`); - } - - WindowContent = (props: JSX.IntrinsicAttributes & WindowProps) => { - props = { ...props, ...this.windowOptions }; - - if (this.windowContent == null) { - return null; - } - - return ; - }; -} \ No newline at end of file diff --git a/packages/core/src/features/apps/appsManager.ts b/packages/core/src/features/apps/appsManager.ts deleted file mode 100644 index cdbaff2..0000000 --- a/packages/core/src/features/apps/appsManager.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { App } from "./app"; - -export class AppsManager { - static APPS: App[] = []; - - static getAppById(id: string): App | null { - let application: App | null = null; - - this.APPS.forEach((app) => { - if (app.id === id) { - application = app; - return; - } - }); - - return application; - } - - /** - * Get the app associated with a file extension - */ - static getAppByFileExtension(fileExtension: string): App | null { - return null; - - // let app: App | null = null; - - // if (IMAGE_FORMATS.includes(fileExtension)) - // return this.getAppById(APPS.MEDIA_VIEWER); - - // switch (fileExtension) { - // default: - // app = this.getAppById(APPS.TEXT_EDITOR); - // break; - // } - - // return app; - } - - /** - * Returns the url of an icon inside the icons folder or the default icon of an app - */ - static getAppIconUrl(appId: string, iconName?: string): string { - if (iconName == null) { - return `/assets/apps/icons/${appId}.svg`; - } else { - return `/assets/apps/${appId}/icons/${iconName}.svg`; - } - } -} \ No newline at end of file diff --git a/packages/core/src/features/apps/index.ts b/packages/core/src/features/apps/index.ts deleted file mode 100644 index 8b4a68f..0000000 --- a/packages/core/src/features/apps/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { AppsManager } from "./appsManager"; -export { App } from "./app"; \ No newline at end of file diff --git a/packages/core/src/features/index.ts b/packages/core/src/features/index.ts index a911c85..4ac4753 100644 --- a/packages/core/src/features/index.ts +++ b/packages/core/src/features/index.ts @@ -1,11 +1,12 @@ +export * from "./system/configs"; +export * from "./virtual-drive"; +export * from "./_utils"; + export { ModalsManager } from "./modals/modalsManager"; export { SettingsManager } from "./settings/settingsManager"; export { StorageManager } from "./storage/storageManager"; export { TrackingManager } from "./tracking/trackingManager"; export { WindowsManager } from "./windows/windowsManager"; export { ZIndexManager } from "./z-index/zIndexManager"; -export * from "./system/configs"; -export * from "./_utils"; -export * from "./apps"; -export * from "./virtual-drive"; + export { Vector2 } from "./math/vector2"; \ No newline at end of file diff --git a/packages/core/src/features/system/configs/app.tsx b/packages/core/src/features/system/configs/app.tsx new file mode 100644 index 0000000..5e6b381 --- /dev/null +++ b/packages/core/src/features/system/configs/app.tsx @@ -0,0 +1,60 @@ +import { Vector2 } from "../../math/vector2"; +import { WindowProps } from "../../../components/windows/WindowView"; +import { FC } from "react"; + +const validIdRegex = /^[a-zA-Z0-9-]+$/; + +export class App { + name: string = "App"; + id: string = "app"; + windowContent: FC; + windowOptions?: { + size: Vector2; + [key: string]: unknown; + }; + + description: string | null = null; + iconUrl: string | null = null; + + isActive: boolean = false; + isPinned?: boolean; + + /** + * @param windowOptions - Default window options + */ + constructor(name: App["name"], id: App["id"], windowContent: App["windowContent"], windowOptions?: App["windowOptions"]) { + this.name = name; + this.id = id; + this.windowContent = windowContent; + this.windowOptions = windowOptions; + + if (this.id.match(validIdRegex) == null) + throw new Error(`Invalid app ID found: ${this.id}` + + "\nApp IDs may only contain letters (a-zA-Z), numbers (0-9) and dashes (-)."); + } + + WindowContent = (props: AppProps) => { + props = { ...props, ...this.windowOptions }; + + if (this.windowContent == null) { + return null; + } + + return ; + }; + + setDescription(description: App["description"]): this { + this.description = description; + return this; + } + + setIconUrl(iconUrl: App["iconUrl"]): this { + this.iconUrl = iconUrl; + return this; + } + + setName(name: string): this { + this.name = name; + return this; + } +} \ No newline at end of file diff --git a/packages/core/src/features/system/configs/appsConfig.ts b/packages/core/src/features/system/configs/appsConfig.ts index da7dfaa..c3c93e6 100644 --- a/packages/core/src/features/system/configs/appsConfig.ts +++ b/packages/core/src/features/system/configs/appsConfig.ts @@ -1,15 +1,58 @@ -import { OptionalInterface } from "../../../types/global"; -import { App } from "../../apps"; +import { App } from "."; +import { OptionalInterface } from "../../../types/util"; export interface AppsConfigOptions { - apps: App[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + apps: App[]; } export class AppsConfig { - apps: AppsConfigOptions["apps"]; + apps: AppsConfigOptions["apps"] = []; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { apps } = options as AppsConfigOptions; - this.apps = apps ?? []; + + const appIds: string[] = []; + apps.forEach((app) => { + if (appIds.includes(app.id)) + throw new Error(`Duplicate app ID found: ${app.id}` + + "\nApp IDs must be unique."); + + this.apps.push(app); + appIds.push(app.id); + }); + } + + getAppById(id: string): App | null { + let resultApp: App | null = null; + + this.apps.forEach((app) => { + if (app.id === id) { + resultApp = app; + return; + } + }); + + return resultApp; + } + + /** + * Get the app associated with a file extension + */ + getAppByFileExtension(fileExtension: string): App | null { + return null; + + // let app: App | null = null; + + // if (IMAGE_FORMATS.includes(fileExtension)) + // return this.getAppById(APPS.MEDIA_VIEWER); + + // switch (fileExtension) { + // default: + // app = this.getAppById(APPS.TEXT_EDITOR); + // break; + // } + + // return app; } } \ No newline at end of file diff --git a/packages/core/src/features/system/configs/desktopConfig.ts b/packages/core/src/features/system/configs/desktopConfig.ts index dd452aa..01b7cb3 100644 --- a/packages/core/src/features/system/configs/desktopConfig.ts +++ b/packages/core/src/features/system/configs/desktopConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; export interface DesktopConfigOptions { /** Array of URLs of wallpaper images */ @@ -25,7 +25,7 @@ export class DesktopConfig { defaultIconSize: DesktopConfigOptions["defaultIconSize"]; defaultIconDirection: DesktopConfigOptions["defaultIconDirection"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { wallpapers, defaultWallpaper, defaultIconSize, defaultIconDirection } = options as DesktopConfigOptions; this.wallpapers = wallpapers ?? [ diff --git a/packages/core/src/features/system/configs/index.ts b/packages/core/src/features/system/configs/index.ts index 1e004f2..92bb1e4 100644 --- a/packages/core/src/features/system/configs/index.ts +++ b/packages/core/src/features/system/configs/index.ts @@ -1,7 +1,9 @@ +export { App } from "./app"; export { AppsConfig } from "./appsConfig"; export { DesktopConfig } from "./desktopConfig"; export { MiscConfig } from "./miscConfig"; export { ModalsConfig } from "./modalsConfig"; export { TaskbarConfig } from "./taskbarConfig"; export { TrackingConfig } from "./trackingConfig"; -export { WindowsConfig } from "./windowsConfig"; \ No newline at end of file +export { WindowsConfig } from "./windowsConfig"; +export { VirtualDriveConfig } from "./virtualDriveConfig"; \ No newline at end of file diff --git a/packages/core/src/features/system/configs/miscConfig.ts b/packages/core/src/features/system/configs/miscConfig.ts index c694d5c..2490dd1 100644 --- a/packages/core/src/features/system/configs/miscConfig.ts +++ b/packages/core/src/features/system/configs/miscConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; export interface MiscConfigOptions { /** @@ -11,8 +11,9 @@ export interface MiscConfigOptions { export class MiscConfig { doubleClickDelay: MiscConfigOptions["doubleClickDelay"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { doubleClickDelay } = options as MiscConfigOptions; + this.doubleClickDelay = doubleClickDelay ?? 250; } } \ No newline at end of file diff --git a/packages/core/src/features/system/configs/modalsConfig.ts b/packages/core/src/features/system/configs/modalsConfig.ts index fa8250e..3576506 100644 --- a/packages/core/src/features/system/configs/modalsConfig.ts +++ b/packages/core/src/features/system/configs/modalsConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; import { Vector2 } from "../../math/vector2"; export interface ModalsConfigOptions { @@ -19,8 +19,9 @@ export class ModalsConfig { defaultDialogSize: ModalsConfigOptions["defaultDialogSize"]; defaultFileSelectorSize: ModalsConfigOptions["defaultFileSelectorSize"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { defaultDialogSize, defaultFileSelectorSize } = options as ModalsConfigOptions; + this.defaultDialogSize = defaultDialogSize ?? new Vector2(400, 200); this.defaultFileSelectorSize = defaultFileSelectorSize ?? new Vector2(700, 400); } diff --git a/packages/core/src/features/system/configs/taskbarConfig.ts b/packages/core/src/features/system/configs/taskbarConfig.ts index bec4578..25b44f6 100644 --- a/packages/core/src/features/system/configs/taskbarConfig.ts +++ b/packages/core/src/features/system/configs/taskbarConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; export interface TaskbarConfigOptions { /** @@ -11,8 +11,9 @@ export interface TaskbarConfigOptions { export class TaskbarConfig { height: TaskbarConfigOptions["height"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { height } = options as TaskbarConfigOptions; + this.height = height ?? 3 * 16; } } \ No newline at end of file diff --git a/packages/core/src/features/system/configs/trackingConfig.ts b/packages/core/src/features/system/configs/trackingConfig.ts index 8b8197c..3c2bcdc 100644 --- a/packages/core/src/features/system/configs/trackingConfig.ts +++ b/packages/core/src/features/system/configs/trackingConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; export interface TrackingConfigOptions { /** @@ -15,8 +15,9 @@ export class TrackingConfig { enabled: TrackingConfigOptions["enabled"]; GAMeasurementId: TrackingConfigOptions["GAMeasurementId"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { enabled, GAMeasurementId } = options as TrackingConfigOptions; + this.enabled = enabled ?? true; this.GAMeasurementId = GAMeasurementId ?? "G-ZFQRR9DP3C"; } diff --git a/packages/core/src/features/system/configs/virtualDriveConfig.ts b/packages/core/src/features/system/configs/virtualDriveConfig.ts new file mode 100644 index 0000000..aa9175e --- /dev/null +++ b/packages/core/src/features/system/configs/virtualDriveConfig.ts @@ -0,0 +1,39 @@ +import { OptionalInterface } from "../../../types/util"; + +export interface VirtualDriveConfigOptions { + fileIcon: string; + infoFileIcon: string; + textFileIcon: string; + codeFileIcon: string; + + folderIcon: string; + imagesFolderIcon: string; + textFolderIcon: string; + folderLinkIcon: string; +} + +export class VirtualDriveConfig { + fileIcon: VirtualDriveConfigOptions["fileIcon"]; + infoFileIcon: VirtualDriveConfigOptions["infoFileIcon"]; + textFileIcon: VirtualDriveConfigOptions["textFileIcon"]; + codeFileIcon: VirtualDriveConfigOptions["codeFileIcon"]; + + folderIcon: VirtualDriveConfigOptions["folderIcon"]; + imagesFolderIcon: VirtualDriveConfigOptions["imagesFolderIcon"]; + textFolderIcon: VirtualDriveConfigOptions["textFolderIcon"]; + folderLinkIcon: VirtualDriveConfigOptions["folderLinkIcon"]; + + constructor(options: OptionalInterface = {}) { + const { fileIcon, infoFileIcon, textFileIcon, codeFileIcon, folderIcon, imagesFolderIcon, textFolderIcon, folderLinkIcon } = options as VirtualDriveConfigOptions; + + this.fileIcon = fileIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/file.svg"; + this.infoFileIcon = infoFileIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/file-info.svg"; + this.textFileIcon = textFileIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/file-text.svg"; + this.codeFileIcon = codeFileIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/file-code.svg"; + + this.folderIcon = folderIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/folder.svg"; + this.imagesFolderIcon = imagesFolderIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/folder-images.svg"; + this.textFolderIcon = textFolderIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/folder-text.svg"; + this.folderLinkIcon = folderLinkIcon ?? "https://os.prozilla.dev/assets/apps/file-explorer/icons/folder-link.svg"; + } +} \ No newline at end of file diff --git a/packages/core/src/features/system/configs/windowsConfig.ts b/packages/core/src/features/system/configs/windowsConfig.ts index db621e4..c3b4c0e 100644 --- a/packages/core/src/features/system/configs/windowsConfig.ts +++ b/packages/core/src/features/system/configs/windowsConfig.ts @@ -1,4 +1,4 @@ -import { OptionalInterface } from "../../../types/global"; +import { OptionalInterface } from "../../../types/util"; import { Vector2 } from "../../math/vector2"; export interface WindowsConfigOptions { @@ -24,8 +24,9 @@ export class WindowsConfig { titleSeparator: WindowsConfigOptions["titleSeparator"]; minScreenSize: WindowsConfigOptions["minScreenSize"]; - constructor(options?: OptionalInterface) { + constructor(options: OptionalInterface = {}) { const { screenMargin, titleSeparator, minScreenSize } = options as WindowsConfigOptions; + this.screenMargin = screenMargin ?? 32; this.titleSeparator = titleSeparator ?? "-"; this.minScreenSize = minScreenSize ?? new Vector2(350, 350); diff --git a/packages/core/src/features/system/systemManager.ts b/packages/core/src/features/system/systemManager.ts index fe21150..1e3b623 100644 --- a/packages/core/src/features/system/systemManager.ts +++ b/packages/core/src/features/system/systemManager.ts @@ -1,4 +1,5 @@ import { formatRelativeTime } from "../_utils"; +import { VirtualDriveConfig } from "./configs"; import { AppsConfig } from "./configs/appsConfig"; import { DesktopConfig } from "./configs/desktopConfig"; import { MiscConfig } from "./configs/miscConfig"; @@ -17,6 +18,7 @@ export interface SystemManagerParams { taskbarConfig: TaskbarConfig; trackingConfig: TrackingConfig; windowsConfig: WindowsConfig; + virtualDriveConfig: VirtualDriveConfig; }; export class SystemManager { @@ -31,6 +33,7 @@ export class SystemManager { taskbarConfig: TaskbarConfig; trackingConfig: TrackingConfig; windowsConfig: WindowsConfig; + virtualDriveConfig: VirtualDriveConfig; constructor({ systemName, @@ -41,7 +44,8 @@ export class SystemManager { modalsConfig, taskbarConfig, trackingConfig, - windowsConfig + windowsConfig, + virtualDriveConfig }: SystemManagerParams) { this.systemName = systemName ?? "ProzillaOS"; this.tagLine = tagLine ?? "Web-based Operating System"; @@ -53,6 +57,7 @@ export class SystemManager { this.taskbarConfig = taskbarConfig; this.trackingConfig = trackingConfig; this.windowsConfig = windowsConfig; + this.virtualDriveConfig = virtualDriveConfig; this.#startDate = new Date(); } diff --git a/packages/core/src/features/virtual-drive/file/virtualFile.ts b/packages/core/src/features/virtual-drive/file/virtualFile.ts index da675e5..f449743 100644 --- a/packages/core/src/features/virtual-drive/file/virtualFile.ts +++ b/packages/core/src/features/virtual-drive/file/virtualFile.ts @@ -1,6 +1,4 @@ -import { APPS } from "../../../constants/apps.const"; import { IMAGE_FORMATS } from "../../../../../apps/media-viewer/config/mediaViewer.config"; -import { AppsManager } from "../../apps/appsManager"; import { WindowsManager } from "../../windows/windowsManager"; import { VirtualBase, VirtualBaseJson } from "../virtualBase"; @@ -107,7 +105,7 @@ export class VirtualFile extends VirtualBase { return await fetch(this.source).then((response) => response.text() ).catch((error) => { - console.error(`Error while reading file with id "${this.id}":`, error); + console.error(`Error while reading file with ID: ${this.id}\n`, error); return null; }) as string; } @@ -125,10 +123,12 @@ export class VirtualFile extends VirtualBase { if (this.source != null && this.extension != null && IMAGE_FORMATS.includes(this.extension)) return this.source; + const { virtualDriveConfig } = this.getRoot().systemManager; + switch (this.extension) { case "txt": case "md": - iconUrl = AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file-text"); + iconUrl = virtualDriveConfig.textFileIcon; break; case "xml": case "js": @@ -139,10 +139,10 @@ export class VirtualFile extends VirtualBase { case "css": case "html": case "yml": - iconUrl = AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file-code"); + iconUrl = virtualDriveConfig.codeFileIcon; break; default: - iconUrl = AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file"); + iconUrl = virtualDriveConfig.fileIcon; break; } diff --git a/packages/core/src/features/virtual-drive/file/virtualFileLink.ts b/packages/core/src/features/virtual-drive/file/virtualFileLink.ts index 30bc285..7726c27 100644 --- a/packages/core/src/features/virtual-drive/file/virtualFileLink.ts +++ b/packages/core/src/features/virtual-drive/file/virtualFileLink.ts @@ -1,6 +1,4 @@ import { VirtualFile } from "."; -import { APPS } from "../../../constants/apps.const"; -import { AppsManager } from "../../apps/appsManager"; import { VirtualFileJson } from "./virtualFile"; export interface VirtualFileLinkJson extends VirtualFileJson { @@ -101,7 +99,9 @@ export class VirtualFileLink extends VirtualFile { } getIconUrl(...args: Parameters): ReturnType { - const defaultIconUrl = AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file"); + const { virtualDriveConfig } = this.getRoot().systemManager; + const defaultIconUrl = virtualDriveConfig.fileIcon; + if (this.isValid()) { return this.iconUrl ?? this.linkedFile?.getIconUrl(...args) ?? defaultIconUrl; } else { diff --git a/packages/core/src/features/virtual-drive/folder/virtualFolder.ts b/packages/core/src/features/virtual-drive/folder/virtualFolder.ts index 181b1c1..9df831a 100644 --- a/packages/core/src/features/virtual-drive/folder/virtualFolder.ts +++ b/packages/core/src/features/virtual-drive/folder/virtualFolder.ts @@ -1,11 +1,10 @@ -import { APPS } from "../../../constants/apps.const"; -import { AppsManager } from "../../apps/appsManager"; import { removeFromArray } from "../../_utils/array.utils"; import { WindowsManager } from "../../windows/windowsManager"; import { VirtualFileJson } from "../file/virtualFile"; import { VirtualBase, VirtualBaseJson } from "../virtualBase"; import { VirtualFolderLink } from "."; import { VirtualFile, VirtualFileLink } from "../file"; +import { fileExplorer } from "@prozilla-os/file-explorer"; export interface VirtualFolderJson extends VirtualBaseJson { fls?: VirtualFileJson[]; @@ -289,7 +288,7 @@ export class VirtualFolder extends VirtualBase { * Opens this folder in file explorer */ open(windowsManager: WindowsManager) { - return windowsManager.open(APPS.FILE_EXPLORER, { path: this.path }); + return windowsManager.open(fileExplorer.id, { path: this.path }); } /** @@ -353,7 +352,8 @@ export class VirtualFolder extends VirtualBase { if (this.iconUrl != null) return this.iconUrl; - return AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "folder"); + const { virtualDriveConfig } = this.getRoot().systemManager; + return virtualDriveConfig.folderIcon; } toJSON(): VirtualFolderJson | null { diff --git a/packages/core/src/features/virtual-drive/folder/virtualFolderLink.ts b/packages/core/src/features/virtual-drive/folder/virtualFolderLink.ts index ef55f74..b08ff5e 100644 --- a/packages/core/src/features/virtual-drive/folder/virtualFolderLink.ts +++ b/packages/core/src/features/virtual-drive/folder/virtualFolderLink.ts @@ -1,5 +1,3 @@ -import { APPS } from "../../../constants/apps.const"; -import { AppsManager } from "../../apps/appsManager"; import { VirtualFolder } from "."; import { VirtualFolderJson } from "./virtualFolder"; @@ -60,7 +58,8 @@ export class VirtualFolderLink extends VirtualFolder { if (this.isValid() && this.linkedFolder?.iconUrl) return this.linkedFolder.iconUrl; - return AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "folder-link"); + const { virtualDriveConfig } = this.getRoot().systemManager; + return virtualDriveConfig.folderLinkIcon; } toJSON(): VirtualFolderLinkJson | null { diff --git a/packages/core/src/features/virtual-drive/root/defaultData.ts b/packages/core/src/features/virtual-drive/root/defaultData.ts index 8de75a3..fe7b940 100644 --- a/packages/core/src/features/virtual-drive/root/defaultData.ts +++ b/packages/core/src/features/virtual-drive/root/defaultData.ts @@ -1,5 +1,3 @@ -import { APPS } from "../../../constants/apps.const"; -import { AppsManager } from "../../apps/appsManager"; import { SystemManager } from "../../system/systemManager"; import { VirtualFile, VirtualFileLink } from "../file"; import { VirtualFolder, VirtualFolderLink } from "../folder"; @@ -9,7 +7,7 @@ import { VirtualRoot } from "./virtualRoot"; * Loads default data on the virtual root */ export function loadDefaultData(systemManager: SystemManager, virtualRoot: VirtualRoot) { - const { desktopConfig } = systemManager; + const { desktopConfig, virtualDriveConfig } = systemManager; const linkedPaths: Record = {}; virtualRoot.createFolder("home", (folder) => { @@ -27,7 +25,7 @@ export function loadDefaultData(systemManager: SystemManager, virtualRoot: Virtu }); }) .createFolder("Pictures", (folder) => { - folder.setIconUrl(AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "folder-images")); + folder.setIconUrl(virtualDriveConfig.imagesFolderIcon); folder.createFolder("Wallpapers", (folder) => { folder.setProtected(true); for (let i = 0; i < desktopConfig.wallpapers.length; i++) { @@ -52,13 +50,13 @@ export function loadDefaultData(systemManager: SystemManager, virtualRoot: Virtu linkedPaths.images = folder.path; }) .createFolder("Documents", (folder) => { - folder.setIconUrl(AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "folder-text")); + folder.setIconUrl(virtualDriveConfig.textFolderIcon); folder.createFile("text", "txt", (file) => { file.setContent("Hello world!"); }).createFile("Info", "md", (file) => { file.setProtected(true) .setSource("/documents/Info.md") - .setIconUrl(AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file-info")); + .setIconUrl(virtualDriveConfig.infoFileIcon); linkedPaths.info = file.path; }).createFile("Prozilla", "md", (file) => { file.setProtected(true) diff --git a/packages/core/src/features/virtual-drive/root/virtualRoot.ts b/packages/core/src/features/virtual-drive/root/virtualRoot.ts index 006f399..c33c82d 100644 --- a/packages/core/src/features/virtual-drive/root/virtualRoot.ts +++ b/packages/core/src/features/virtual-drive/root/virtualRoot.ts @@ -19,7 +19,7 @@ export class VirtualRoot extends VirtualFolder { shortcuts: Record; initiated: boolean = false; loadedDefaultData: boolean = false; - #systemManager: SystemManager; + systemManager: SystemManager; static EVENT_NAMES = { ERROR: "error" @@ -28,13 +28,13 @@ export class VirtualRoot extends VirtualFolder { constructor(systemManager: SystemManager) { super("root"); this.root = this; - this.#systemManager = systemManager; + this.systemManager = systemManager; this.isRoot = true; this.shortcuts = {}; } loadDefaultData() { - loadDefaultData(this.#systemManager, this); + loadDefaultData(this.systemManager, this); } loadData() { diff --git a/packages/core/src/features/virtual-drive/virtualBase.ts b/packages/core/src/features/virtual-drive/virtualBase.ts index dd02265..eb00371 100644 --- a/packages/core/src/features/virtual-drive/virtualBase.ts +++ b/packages/core/src/features/virtual-drive/virtualBase.ts @@ -1,5 +1,3 @@ -import { APPS } from "../../constants/apps.const"; -import { AppsManager } from "../apps/appsManager"; import { EventEmitter, EventNamesMap } from "../_utils/event.utils"; import { VirtualRoot } from "./root/virtualRoot"; import { VirtualFile } from "./file"; @@ -81,10 +79,12 @@ export class VirtualBase extends EventEmitter { } getIconUrl(): string { - return this.iconUrl - ?? this.linkedFile?.iconUrl - ?? this.linkedFolder?.iconUrl - ?? AppsManager.getAppIconUrl(APPS.FILE_EXPLORER, "file"); + if (this.iconUrl != null) return this.iconUrl; + if (this.linkedFile?.iconUrl != null) return this.linkedFile.iconUrl; + if (this.linkedFolder?.iconUrl != null) return this.linkedFolder.iconUrl; + + const { virtualDriveConfig } = this.getRoot().systemManager; + return virtualDriveConfig.fileIcon; } getType(): string { diff --git a/packages/core/src/features/windows/windowsManager.ts b/packages/core/src/features/windows/windowsManager.ts index d6faa10..6262cb4 100644 --- a/packages/core/src/features/windows/windowsManager.ts +++ b/packages/core/src/features/windows/windowsManager.ts @@ -1,6 +1,5 @@ import { randomRange } from "../_utils/math.utils"; -import { App } from "../apps/app"; -import { AppsManager } from "../apps/appsManager"; +import { App } from "../system/configs/app"; import { Vector2 } from "../math/vector2"; import { SystemManager } from "../system/systemManager"; import { TrackingManager } from "../tracking/trackingManager"; @@ -36,7 +35,8 @@ export class WindowsManager { } open(appId: string, options?: WindowOptions | null): object | null { - const app = AppsManager.getAppById(appId); + const { appsConfig, windowsConfig, taskbarConfig } = this.#systemManager; + const app = appsConfig.getAppById(appId); if (app == null) { console.warn(`Failed to open app ${appId}: app not found`); @@ -44,8 +44,7 @@ export class WindowsManager { } const size = options?.size ?? app.windowOptions?.size ?? new Vector2(700, 400); - - const { windowsConfig, taskbarConfig } = this.#systemManager; + const availableScreenSpace = new Vector2( window.innerWidth - windowsConfig.screenMargin * 2, window.innerHeight - windowsConfig.screenMargin * 2 - taskbarConfig.height @@ -112,7 +111,8 @@ export class WindowsManager { openFile(file: VirtualFile, options: object = {}): object | null { if (file.extension == null) return null; - const app = AppsManager.getAppByFileExtension(file?.extension); + const { appsConfig } = this.#systemManager; + const app = appsConfig.getAppByFileExtension(file?.extension); if (app != null) { return this.open(app.id, { file, ...options }); } else { diff --git a/packages/core/src/hooks/apps/appFolder.ts b/packages/core/src/hooks/apps/appFolder.ts index 8608e38..305aeff 100644 --- a/packages/core/src/hooks/apps/appFolder.ts +++ b/packages/core/src/hooks/apps/appFolder.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { App } from "../../features/apps/app"; +import { App } from "../../features/system/configs/app"; import { VirtualFolder } from "../../features/virtual-drive/folder"; import { useVirtualRoot } from "../virtual-drive/virtualRootContext"; diff --git a/packages/core/src/hooks/system/systemManagerProvider.tsx b/packages/core/src/hooks/system/systemManagerProvider.tsx index 5eaed8d..bf5c6c6 100644 --- a/packages/core/src/hooks/system/systemManagerProvider.tsx +++ b/packages/core/src/hooks/system/systemManagerProvider.tsx @@ -12,6 +12,7 @@ interface SystemManagerProviderProps { taskbarConfig: SystemManagerParams["taskbarConfig"]; trackingConfig: SystemManagerParams["trackingConfig"]; windowsConfig: SystemManagerParams["windowsConfig"]; + virtualDriveConfig: SystemManagerParams["virtualDriveConfig"]; children: ReactNode; } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 04821fe..68035a1 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,6 +1,5 @@ -export * from "./components"; export * from "./features"; +export * from "./styles"; +export * from "./components"; export * from "./hooks"; -export { default as utilStyles } from "./src/styles/utils.module.css"; -export { DIALOG_CONTENT_TYPES } from "./constants/modals.const"; -export { CODE_EXTENSIONS } from "./constants/virtualDrive.const"; \ No newline at end of file +export * from "./constants"; diff --git a/packages/core/src/styles/index.ts b/packages/core/src/styles/index.ts new file mode 100644 index 0000000..67d9480 --- /dev/null +++ b/packages/core/src/styles/index.ts @@ -0,0 +1,3 @@ +import "./global.css"; + +export { default as utilStyles } from "./utils.module.css"; \ No newline at end of file diff --git a/packages/core/src/types/global.d.ts b/packages/core/src/types/util.d.ts similarity index 100% rename from packages/core/src/types/global.d.ts rename to packages/core/src/types/util.d.ts diff --git a/scripts/_utils/print.ts b/scripts/_utils/print.ts index 0ee3420..f26cd84 100644 --- a/scripts/_utils/print.ts +++ b/scripts/_utils/print.ts @@ -1,4 +1,4 @@ -import { ANSI } from "../../src/config/apps/terminal.config"; +import { ANSI } from "@prozilla-os/core"; export type status = "error" | "info" | "file" | "success" | "start"; diff --git a/scripts/fetchRepository.ts b/scripts/fetchRepository.ts index cd9203b..b77e483 100644 --- a/scripts/fetchRepository.ts +++ b/scripts/fetchRepository.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; -import { ANSI } from "../src/config/apps/terminal.config"; import { REPO } from "../src/config/deploy.config"; +import { ANSI } from "@prozilla-os/core"; const API_URL = "https://api.github.com/"; const TREE_PATH = "public/config/tree.json"; diff --git a/src/Main.tsx b/src/Main.tsx index 595d435..f2c6677 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -2,13 +2,20 @@ import { ReactElement } from "react"; import { Router } from "./router/Router"; import { ProzillaOS } from "@prozilla-os/core"; import { desktopConfig } from "./config/desktop.config"; +import { NAME, TAG_LINE } from "./config/branding.config"; +import { appsConfig } from "./config/apps.config"; +import { virtualDriveConfig } from "./config/virtualDrive.config"; export function Main(): ReactElement { return ; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/standalone-header/StandaloneHeader.module.css b/src/components/standalone/StandaloneHeader.module.css similarity index 100% rename from src/components/standalone-header/StandaloneHeader.module.css rename to src/components/standalone/StandaloneHeader.module.css diff --git a/src/components/standalone-header/StandaloneHeader.tsx b/src/components/standalone/StandaloneHeader.tsx similarity index 100% rename from src/components/standalone-header/StandaloneHeader.tsx rename to src/components/standalone/StandaloneHeader.tsx diff --git a/src/config/apps.config.ts b/src/config/apps.config.ts new file mode 100644 index 0000000..0265773 --- /dev/null +++ b/src/config/apps.config.ts @@ -0,0 +1,8 @@ +import { AppsConfig } from "@prozilla-os/core"; +import { fileExplorer } from "@prozilla-os/file-explorer"; + +export const appsConfig = new AppsConfig({ + apps: [ + fileExplorer.setName("Files"), + ], +}); \ No newline at end of file diff --git a/src/config/branding.config.ts b/src/config/branding.config.ts index 351c411..bb9f28a 100644 --- a/src/config/branding.config.ts +++ b/src/config/branding.config.ts @@ -1,4 +1,4 @@ -import { ANSI } from "./apps/terminal.config"; +import { ANSI } from "@prozilla-os/core"; export const NAME = "ProzillaOS"; export const TAG_LINE = "Web-based Operating System"; diff --git a/src/config/virtualDrive.config.ts b/src/config/virtualDrive.config.ts new file mode 100644 index 0000000..8bab362 --- /dev/null +++ b/src/config/virtualDrive.config.ts @@ -0,0 +1,12 @@ +import { VirtualDriveConfig } from "@prozilla-os/core"; + +export const virtualDriveConfig = new VirtualDriveConfig({ + fileIcon: "/assets/apps/file-explorer/icons/file.svg", + infoFileIcon: "/assets/apps/file-explorer/icons/file-info.svg", + textFileIcon: "/assets/apps/file-explorer/icons/file-text.svg", + codeFileIcon: "/assets/apps/file-explorer/icons/file-code.svg", + folderIcon: "/assets/apps/file-explorer/icons/folder.svg", + imagesFolderIcon: "/assets/apps/file-explorer/icons/folder-images.svg", + textFolderIcon: "/assets/apps/file-explorer/icons/folder-text.svg", + folderLinkIcon: "/assets/apps/file-explorer/icons/folder-link.svg", +}); \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index ca30058..1e3e1fe 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,5 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import "./styles/global.css"; import { Main } from "./Main"; import { ASCII_LOGO, NAME } from "./config/branding.config"; diff --git a/src/router/Router.tsx b/src/router/Router.tsx index 5d211af..8ae7597 100644 --- a/src/router/Router.tsx +++ b/src/router/Router.tsx @@ -2,14 +2,16 @@ import { BrowserRouter, Route, Routes } from "react-router-dom"; import { DefaultRoute } from "./routes/DefaultRoute"; import { StandaloneRoute } from "./routes/StandaloneRoute"; import { NoRoute } from "./routes/NoRoute"; -import { App, AppsManager } from "@prozilla-os/core"; +import { useSystemManager } from "@prozilla-os/core"; export function Router() { + const { appsConfig } = useSystemManager(); + return }/> - {AppsManager.APPS.map((app: App) => + {appsConfig.apps.map((app) => }/> )} }/> diff --git a/src/router/routes/StandaloneRoute.tsx b/src/router/routes/StandaloneRoute.tsx index 366c188..de50626 100644 --- a/src/router/routes/StandaloneRoute.tsx +++ b/src/router/routes/StandaloneRoute.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect, useState } from "react"; import styles from "./StandaloneRoute.module.css"; import { NAME } from "../../config/branding.config"; -import { App, AppsManager, generateUrl, getViewportParams, ModalsView, openUrl, setViewportIcon, setViewportTitle } from "@prozilla-os/core"; -import { StandaloneHeader } from "../../components/standalone-header/StandaloneHeader"; +import { App, generateUrl, getViewportParams, ModalsView, openUrl, setViewportIcon, setViewportTitle } from "@prozilla-os/core"; +import { StandaloneHeader } from "../../components/standalone/StandaloneHeader"; interface StandaloneRouteProps { app: App; @@ -10,7 +10,7 @@ interface StandaloneRouteProps { export function StandaloneRoute({ app }: StandaloneRouteProps) { const [title, setTitle] = useState(app.name); - const [iconUrl, setIconUrl] = useState(AppsManager.getAppIconUrl(app.id)); + const [iconUrl, setIconUrl] = useState(app.iconUrl ?? ""); useEffect(() => { // TO DO: don't overwrite metadata in production diff --git a/tsconfig.json b/tsconfig.json index ad57f2b..a60ee32 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,7 +29,7 @@ "include": [ "src/**/*", "vite.config.ts", - "scripts/**/*", + // "scripts/**/*", // TO DO: uncomment this line ], "exclude": [ "./node_modules",