Added router

This commit is contained in:
Prozilla 2024-06-09 13:02:38 +02:00
parent a369a20701
commit 14015ce28e
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
39 changed files with 405 additions and 87 deletions

141
package-lock.json generated
View file

@ -44,6 +44,7 @@
"eslint-plugin-react": "^7.34.1", "eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-refresh": "^0.4.7", "eslint-plugin-react-refresh": "^0.4.7",
"gh-pages": "^5.0.0", "gh-pages": "^5.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5", "typescript": "^5.4.5",
"typescript-eslint": "^7.8.0", "typescript-eslint": "^7.8.0",
"web-vitals": "^4.0.1" "web-vitals": "^4.0.1"
@ -513,6 +514,28 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.20.2", "version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
@ -1800,6 +1823,30 @@
"tslib": "^2.6.0" "tslib": "^2.6.0"
} }
}, },
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
@ -2130,6 +2177,15 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
} }
}, },
"node_modules/acorn-walk": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
"integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ajv": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -2171,6 +2227,12 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/array-buffer-byte-length": { "node_modules/array-buffer-byte-length": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
@ -2565,6 +2627,12 @@
"url": "https://opencollective.com/core-js" "url": "https://opencollective.com/core-js"
} }
}, },
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -2692,6 +2760,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dir-glob": { "node_modules/dir-glob": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -4575,6 +4652,12 @@
"semver": "bin/semver" "semver": "bin/semver"
} }
}, },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/markdown-to-jsx": { "node_modules/markdown-to-jsx": {
"version": "7.2.1", "version": "7.2.1",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.2.1.tgz", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.2.1.tgz",
@ -5788,6 +5871,49 @@
"typescript": ">=4.2.0" "typescript": ">=4.2.0"
} }
}, },
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.6.0", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
@ -5985,6 +6111,12 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/vite": { "node_modules/vite": {
"version": "5.2.12", "version": "5.2.12",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz",
@ -6205,6 +6337,15 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}, },
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": { "node_modules/yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View file

@ -10,8 +10,9 @@
"start": "vite --port 3000 --host", "start": "vite --port 3000 --host",
"build": "tsc && vite build", "build": "tsc && vite build",
"serve": "vite preview", "serve": "vite preview",
"predeploy": "npm run build", "predeploy": "npm run sitemap && npm run build",
"deploy": "sh deploy.sh" "deploy": "sh deploy.sh",
"sitemap": "node --experimental-specifier-resolution=node --loader ts-node/esm ./src/tools/sitemapGenerator.js"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
@ -50,6 +51,7 @@
"eslint-plugin-react": "^7.34.1", "eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-refresh": "^0.4.7", "eslint-plugin-react-refresh": "^0.4.7",
"gh-pages": "^5.0.0", "gh-pages": "^5.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5", "typescript": "^5.4.5",
"typescript-eslint": "^7.8.0", "typescript-eslint": "^7.8.0",
"web-vitals": "^4.0.1" "web-vitals": "^4.0.1"

View file

@ -4,38 +4,67 @@
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"> xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url> <url>
<loc>https://os.prozilla.dev/</loc> <loc>https://os.prozilla.dev/</loc>
<lastmod>2024-6-9</lastmod>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/banner-logo-title.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/vibrant-wallpaper-blue-purple-red.png</image:loc>
</image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/screenshots/screenshot-files-info-taskbar-desktop.png</image:loc>
</image:image> </image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/abstract-mesh-gradient-orange-red-purple.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/abstract-mesh-gradient-orange-red-purple.png</image:loc>
</image:image> </image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/vibrant-wallpaper-purple-yellow.png</image:loc>
</image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/abstract-wallpaper-mesh-gradient-cyan.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/abstract-wallpaper-mesh-gradient-cyan.png</image:loc>
</image:image> </image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/colorful-abstract-wallpaper-blue-red-green.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/colorful-abstract-wallpaper-blue-red-green.png</image:loc>
</image:image> </image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/colorful-mesh-gradient-red-green.png</image:loc>
</image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/mesh-gradient-wallpaper-red-purple.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/mesh-gradient-wallpaper-red-purple.png</image:loc>
</image:image> </image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/vibrant-wallpaper-blue-purple-red.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/colorful-mesh-gradient-red-green.png</image:loc>
</image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/vibrant-wallpaper-purple-yellow.png</image:loc>
</image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/wave-abstract-wallpaper-teal.png</image:loc>
</image:image> </image:image>
<image:image> <image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/flame-abstract-wallpaper-orange.png</image:loc> <image:loc>https://os.prozilla.dev/assets/wallpapers/flame-abstract-wallpaper-orange.png</image:loc>
</image:image> </image:image>
<image:image>
<image:loc>https://os.prozilla.dev/assets/wallpapers/wave-abstract-wallpaper-teal.png</image:loc>
</image:image>
</url>
<url>
<loc>https://os.prozilla.dev/terminal</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/settings</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/media-viewer</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/text-editor</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/file-explorer</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/calculator</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/browser</loc>
<lastmod>2024-6-9</lastmod>
</url>
<url>
<loc>https://os.prozilla.dev/logic-sim</loc>
<lastmod>2024-6-9</lastmod>
</url> </url>
</urlset> </urlset>

View file

@ -1,8 +1,4 @@
import styles from "./App.module.css"; import styles from "./App.module.css";
import { Taskbar } from "./components/taskbar/Taskbar";
import { WindowsView } from "./components/windows/WindowsView";
import { Desktop } from "./components/desktop/Desktop";
import { ModalsView } from "./components/modals/ModalsView";
import { ReactElement, useEffect } from "react"; import { ReactElement, useEffect } from "react";
import { ZIndexManagerProvider } from "./hooks/z-index/zIndexManagerProvider"; import { ZIndexManagerProvider } from "./hooks/z-index/zIndexManagerProvider";
import { ThemeProvider } from "./hooks/themes/themes"; import { ThemeProvider } from "./hooks/themes/themes";
@ -10,6 +6,7 @@ import { VirtualRootProvider } from "./hooks/virtual-drive/virtualRootProvider";
import { WindowsManagerProvider } from "./hooks/windows/windowsManagerProvider"; import { WindowsManagerProvider } from "./hooks/windows/windowsManagerProvider";
import { ModalsManagerProvider } from "./hooks/modals/modalsManagerProvider"; import { ModalsManagerProvider } from "./hooks/modals/modalsManagerProvider";
import { SettingsManagerProvider } from "./hooks/settings/settingsManagerProvider"; import { SettingsManagerProvider } from "./hooks/settings/settingsManagerProvider";
import { Router } from "./components/router/Router";
export default function App(): ReactElement { export default function App(): ReactElement {
useEffect(() => { useEffect(() => {
@ -31,10 +28,7 @@ export default function App(): ReactElement {
<SettingsManagerProvider> <SettingsManagerProvider>
<ThemeProvider> <ThemeProvider>
<div className={styles.App}> <div className={styles.App}>
<Taskbar/> <Router/>
<WindowsView/>
<ModalsView/>
<Desktop/>
</div> </div>
</ThemeProvider> </ThemeProvider>
</SettingsManagerProvider> </SettingsManagerProvider>

View file

@ -1,18 +1,21 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import styles from "./Button.module.css"; import styles from "./Button.module.css";
import { faExternalLink } from "@fortawesome/free-solid-svg-icons"; import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
import { ReactNode } from "react"; import { HTMLAttributeAnchorTarget, ReactNode } from "react";
import { IconProp } from "@fortawesome/fontawesome-svg-core";
interface ButtonProps { interface ButtonProps {
className?: string; className?: string;
href?: string; href?: string;
icon?: IconProp;
target?: HTMLAttributeAnchorTarget;
children?: ReactNode; children?: ReactNode;
[key: string]: any; [key: string]: unknown;
} }
export function Button(props: ButtonProps) { export function Button(props: ButtonProps) {
let { className = "" } = props; let { className = "" } = props;
const { href, children } = props; const { href, children, icon, target } = props;
className = `${styles.Button} ${className}`; className = `${styles.Button} ${className}`;
@ -21,14 +24,14 @@ export function Button(props: ButtonProps) {
return (<a return (<a
href={href} href={href}
target="_blank" target={target ?? "_blank"}
rel="noreferrer" rel="noreferrer"
tabIndex={0} tabIndex={0}
{...props} {...props}
className={className} className={className}
> >
{children} {children}
<FontAwesomeIcon icon={faExternalLink}/> <FontAwesomeIcon icon={icon ?? faExternalLink}/>
</a>); </a>);
} else { } else {
return (<button return (<button

View file

@ -24,7 +24,7 @@ import { CODE_FORMATS } from "../../../config/apps/textEditor.config";
import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config"; import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config";
import { WindowProps } from "../../windows/WindowView"; import { WindowProps } from "../../windows/WindowView";
import { VirtualFolder } from "../../../features/virtual-drive/folder/virtualFolder"; import { VirtualFolder } from "../../../features/virtual-drive/folder/virtualFolder";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
import { VirtualFolderLink } from "../../../features/virtual-drive/folder/virtualFolderLink"; import { VirtualFolderLink } from "../../../features/virtual-drive/folder/virtualFolderLink";
import ImportButton from "./ImportButton"; import ImportButton from "./ImportButton";
import { useAlert } from "../../../hooks/modals/alert"; import { useAlert } from "../../../hooks/modals/alert";

View file

@ -2,7 +2,7 @@ import { FormEventHandler, ReactElement } from "react";
import styles from "./FileExplorer.module.css"; import styles from "./FileExplorer.module.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faDownload } from "@fortawesome/free-solid-svg-icons"; import { faDownload } from "@fortawesome/free-solid-svg-icons";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
import { VirtualFolder } from "../../../features/virtual-drive/folder"; import { VirtualFolder } from "../../../features/virtual-drive/folder";
interface ImportButtonProps { interface ImportButtonProps {

View file

@ -1,5 +1,5 @@
import { MouseEventHandler, ReactElement, useEffect, useRef, useState } from "react"; import { MouseEventHandler, ReactElement, useEffect, useRef, useState } from "react";
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../../features/virtual-drive/file";
import { VirtualFolder } from "../../../../features/virtual-drive/folder/virtualFolder"; import { VirtualFolder } from "../../../../features/virtual-drive/folder/virtualFolder";
import { Interactable } from "../../../_utils/interactable/Interactable"; import { Interactable } from "../../../_utils/interactable/Interactable";
import styles from "./DirectoryList.module.css"; import styles from "./DirectoryList.module.css";

View file

@ -4,7 +4,7 @@ import { useWindowsManager } from "../../../hooks/windows/windowsManagerContext"
import styles from "./MediaViewer.module.css"; import styles from "./MediaViewer.module.css";
import { APPS } from "../../../config/apps.config"; import { APPS } from "../../../config/apps.config";
import { IMAGE_FORMATS } from "../../../config/apps/mediaViewer.config"; import { IMAGE_FORMATS } from "../../../config/apps/mediaViewer.config";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
import { WindowProps } from "../../windows/WindowView"; import { WindowProps } from "../../windows/WindowView";
interface MediaViewerProps extends WindowProps { interface MediaViewerProps extends WindowProps {

View file

@ -11,7 +11,7 @@ import { FileSelector } from "../../../modals/file-selector/FileSelector";
import { SELECTOR_MODE } from "../../../../config/apps/fileExplorer.config"; import { SELECTOR_MODE } from "../../../../config/apps/fileExplorer.config";
import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../../config/modals.config"; import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../../config/modals.config";
import { IMAGE_FORMATS } from "../../../../config/apps/mediaViewer.config"; import { IMAGE_FORMATS } from "../../../../config/apps/mediaViewer.config";
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../../features/virtual-drive/file";
import { VirtualFolder } from "../../../../features/virtual-drive/folder/virtualFolder"; import { VirtualFolder } from "../../../../features/virtual-drive/folder/virtualFolder";
import { THEMES } from "../../../../config/themes.config"; import { THEMES } from "../../../../config/themes.config";

View file

@ -13,7 +13,7 @@ import { useWindowedModal } from "../../../hooks/modals/windowedModal";
import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../config/modals.config"; import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../config/modals.config";
import { FileSelector } from "../../modals/file-selector/FileSelector"; import { FileSelector } from "../../modals/file-selector/FileSelector";
import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config"; import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
import { WindowProps } from "../../windows/WindowView"; import { WindowProps } from "../../windows/WindowView";
import { DropdownAction } from "../../actions/actions/DropdownAction"; import { DropdownAction } from "../../actions/actions/DropdownAction";
import { ClickAction } from "../../actions/actions/ClickAction"; import { ClickAction } from "../../actions/actions/ClickAction";

View file

@ -1,19 +1,11 @@
import { useMemo } from "react"; import { useMemo } from "react";
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile";
import ModalsManager from "../../../../features/modals/modalsManager";
import App from "../../../../features/apps/app";
import WindowsManager from "../../../../features/windows/windowsManager";
/** interface MarkdownImageProps {
* @param {object} props src: string;
* @param {VirtualFile} props.currentFile alt: string
* @param {string} props.src }
* @param {string} props.alt
* @param {ModalsManager} props.modalsManager export function MarkdownImage({ alt, src, ...props }: MarkdownImageProps) {
* @param {WindowsManager} props.windowsManager
* @param {App} props.app
*/
export function MarkdownImage({ currentFile, alt, src, modalsManager, windowsManager, app, ...props }) {
const source = useMemo(() => { const source = useMemo(() => {
if (src.startsWith("public")) { if (src.startsWith("public")) {
return src.replace(/^public\//g, "/"); return src.replace(/^public\//g, "/");

View file

@ -1,9 +1,9 @@
import { useMemo } from "react"; import { MouseEventHandler, ReactNode, useMemo } from "react";
import { faExternalLink } from "@fortawesome/free-solid-svg-icons"; import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
import { useContextMenu } from "../../../../hooks/modals/contextMenu"; import { useContextMenu } from "../../../../hooks/modals/contextMenu";
import { Actions } from "../../../actions/Actions"; import { Actions } from "../../../actions/Actions";
import { ClickAction } from "../../../actions/actions/ClickAction"; import { ClickAction } from "../../../actions/actions/ClickAction";
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../../features/virtual-drive/file";
import { useWindowedModal } from "../../../../hooks/modals/windowedModal"; import { useWindowedModal } from "../../../../hooks/modals/windowedModal";
import AppsManager from "../../../../features/apps/appsManager"; import AppsManager from "../../../../features/apps/appsManager";
import App from "../../../../features/apps/app"; import App from "../../../../features/apps/app";
@ -13,19 +13,19 @@ import Vector2 from "../../../../features/math/vector2";
import WindowsManager from "../../../../features/windows/windowsManager"; import WindowsManager from "../../../../features/windows/windowsManager";
import { APPS } from "../../../../config/apps.config"; import { APPS } from "../../../../config/apps.config";
/** interface MarkdownLinkProps {
* @param {object} props href: string;
* @param {string} props.href children: ReactNode;
* @param {*} props.children windowsManager: WindowsManager;
* @param {WindowsManager} props.windowsManager setCurrentFile: Function;
* @param {Function} props.setCurrentFile currentFile: VirtualFile;
* @param {VirtualFile} props.currentFile app: App;
* @param {App} props.app }
*/
export function MarkdownLink({ href, children, windowsManager, currentFile, setCurrentFile, app, ...props }) { export function MarkdownLink({ href, children, windowsManager, currentFile, setCurrentFile, app, ...props }: MarkdownLinkProps) {
const { openWindowedModal } = useWindowedModal(); const { openWindowedModal } = useWindowedModal();
const onClick = (event) => { const onClick = (event: MouseEvent) => {
event.preventDefault(); event.preventDefault();
if (!href.startsWith("http://") && !href.startsWith("https://")) { if (!href.startsWith("http://") && !href.startsWith("https://")) {
@ -59,8 +59,8 @@ export function MarkdownLink({ href, children, windowsManager, currentFile, setC
</Actions> </Actions>
}); });
const title = useMemo(() => { const title = useMemo<string>(() => {
let title = null; let title: string = null;
try { try {
title = new URL(href).hostname; title = new URL(href).hostname;
} catch (error) { } catch (error) {
@ -74,7 +74,7 @@ export function MarkdownLink({ href, children, windowsManager, currentFile, setC
rel="noreferrer" rel="noreferrer"
href={href} href={href}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
onClick={onClick} onClick={onClick as unknown as MouseEventHandler}
{...props} {...props}
title={title} title={title}
> >

View file

@ -24,7 +24,7 @@ import { Share } from "../modals/share/Share";
import ModalsManager from "../../features/modals/modalsManager"; import ModalsManager from "../../features/modals/modalsManager";
import { VirtualFolder } from "../../features/virtual-drive/folder/virtualFolder"; import { VirtualFolder } from "../../features/virtual-drive/folder/virtualFolder";
import { VirtualFolderLink } from "../../features/virtual-drive/folder/virtualFolderLink"; import { VirtualFolderLink } from "../../features/virtual-drive/folder/virtualFolderLink";
import { VirtualFile } from "../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../features/virtual-drive/file";
import { TABS } from "../../config/apps/settings.config"; import { TABS } from "../../config/apps/settings.config";
export const Desktop = memo(() => { export const Desktop = memo(() => {

View file

@ -5,7 +5,7 @@ import utilStyles from "../../../styles/utils.module.css";
import { StorageManager } from "../../../features/storage/storageManager"; import { StorageManager } from "../../../features/storage/storageManager";
import AppsManager from "../../../features/apps/appsManager"; import AppsManager from "../../../features/apps/appsManager";
import { ModalProps } from "../ModalView.js"; import { ModalProps } from "../ModalView.js";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
interface FilePropetiesProps extends ModalProps { interface FilePropetiesProps extends ModalProps {
file: VirtualFile; file: VirtualFile;

View file

@ -5,7 +5,7 @@ import { Button } from "../../_utils/button/Button";
import { FileExplorer } from "../../apps/file-explorer/FileExplorer"; import { FileExplorer } from "../../apps/file-explorer/FileExplorer";
import { WindowedModal } from "../_utils/WindowedModal"; import { WindowedModal } from "../_utils/WindowedModal";
import styles from "./FileSelector.module.css"; import styles from "./FileSelector.module.css";
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../features/virtual-drive/file";
import { ModalProps } from "../ModalView"; import { ModalProps } from "../ModalView";
import { VirtualFolder } from "../../../features/virtual-drive/folder"; import { VirtualFolder } from "../../../features/virtual-drive/folder";

View file

@ -0,0 +1,20 @@
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { DefaultRoute } from "./routes/DefaultRoute";
import AppsManager from "../../features/apps/appsManager";
import App from "../../features/apps/app";
import { AppRoute } from "./routes/AppRoute";
import { NoRoute } from "./routes/NoRoute";
export function Router() {
return <BrowserRouter>
<Routes>
<Route path="/">
<Route index element={<DefaultRoute/>}/>
{AppsManager.APPS.map((app: App) =>
<Route path={app.id} key={app.id} element={<AppRoute app={app}/>}/>
)}
<Route path="*" element={<NoRoute/>}/>
</Route>
</Routes>
</BrowserRouter>;
}

View file

@ -0,0 +1,30 @@
import { useEffect, useState } from "react";
import App from "../../../features/apps/app";
import AppsManager from "../../../features/apps/appsManager";
import { setViewportIcon, setViewportTitle } from "../../../features/_utils/browser.utils";
import { NAME } from "../../../config/branding.config";
interface AppRouteProps {
app: App;
}
export function AppRoute({ app }: AppRouteProps) {
const [title, setTitle] = useState(app.name);
const [iconUrl, setIconUrl] = useState(AppsManager.getAppIconUrl(app.id));
useEffect(() => {
const setViewportTitleAndIcon = () => {
setViewportTitle(`${title} | ${NAME}`);
setViewportIcon(iconUrl);
};
setViewportTitleAndIcon();
}, [iconUrl, title]);
return <app.WindowContent
app={app}
setTitle={setTitle}
setIconUrl={setIconUrl}
active={true}
/>;
}

View file

@ -0,0 +1,13 @@
import { Desktop } from "../../desktop/Desktop";
import { ModalsView } from "../../modals/ModalsView";
import { Taskbar } from "../../taskbar/Taskbar";
import { WindowsView } from "../../windows/WindowsView";
export function DefaultRoute() {
return <>
<Taskbar/>
<WindowsView/>
<ModalsView/>
<Desktop/>
</>;
}

View file

@ -0,0 +1,23 @@
.NoRoute {
display: flex;
flex-direction: column;
gap: 1rem;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.Title {
margin: 0;
font-size: 2rem;
}
.Link {
--normal-color: var(--background-color-0) !important;
--hover-color: var(--background-color-1) !important;
margin-bottom: 0.75rem !important;
padding: 0.5rem 1rem;
border-radius: var(--border-radius-1);
}

View file

@ -0,0 +1,11 @@
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import utilStyles from "../../../styles/utils.module.css";
import { Button } from "../../_utils/button/Button";
import styles from "./NoRoute.module.css";
export function NoRoute() {
return <span className={styles.NoRoute}>
<p className={`${styles.Title} ${utilStyles.TextSemibold}`}>404: Not Found</p>
<Button className={styles.Link} icon={faArrowRight} href="/" target="_self">Home</Button>
</span>;
}

View file

@ -2,6 +2,7 @@ import { ANSI } from "./apps/terminal.config";
export const NAME = "ProzillaOS"; export const NAME = "ProzillaOS";
export const TAG_LINE = "Web-based Operating System"; export const TAG_LINE = "Web-based Operating System";
export const BASE_URL = "https://os.prozilla.dev/";
export const ASCII_LOGO = ` export const ASCII_LOGO = `
:. :.

View file

@ -29,6 +29,10 @@ export function isValidUrl(string: string): boolean {
export function setViewportTitle(title: string) { export function setViewportTitle(title: string) {
document.title = title; document.title = title;
document.querySelectorAll("meta[property='og:title'], meta[name='twitter:title']")?.forEach((element) => {
element.setAttribute("content", title);
});
} }
export function setViewportIcon(url: string) { export function setViewportIcon(url: string) {

View file

@ -36,7 +36,7 @@ export default class AppsManager {
new App(APP_NAMES.BROWSER, APPS.BROWSER, Browser, { new App(APP_NAMES.BROWSER, APPS.BROWSER, Browser, {
size: new Vector2(700, 500) size: new Vector2(700, 500)
}), }),
new App("Logic Sim (WIP)", "logic-sim", LogicSim), new App("Logic Sim (WIP)", APPS.LOGIC_SIM, LogicSim),
]; ];
static getAppById(id: string): App | null { static getAppById(id: string): App | null {

View file

@ -78,7 +78,7 @@ export default class Command {
} }
getOption(key: string): Option { getOption(key: string): Option {
let matchingOption = null; let matchingOption: Option = null;
this.options.forEach((option) => { this.options.forEach((option) => {
if (option.short === key || option.long === key) if (option.short === key || option.long === key)

View file

@ -1,4 +1,4 @@
import { VirtualFile } from "../../../virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../virtual-drive/file";
import { formatError } from "../_utils/terminal.utils"; import { formatError } from "../_utils/terminal.utils";
import Command from "../command"; import Command from "../command";
@ -14,7 +14,7 @@ export const cat = new Command()
const file = currentDirectory.findFile(name, extension); const file = currentDirectory.findFile(name, extension);
if (!file) if (!file)
return formatError(this.name, `${args[0]}: No such file`); return formatError((this as Command).name, `${args[0]}: No such file`);
if (file.content) { if (file.content) {
if (!options.includes("e")) { if (!options.includes("e")) {

View file

@ -1,4 +1,4 @@
import { VirtualFile } from "../../../virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../virtual-drive/file";
import { formatError } from "../_utils/terminal.utils"; import { formatError } from "../_utils/terminal.utils";
import Command from "../command"; import Command from "../command";
@ -12,7 +12,7 @@ export const rm = new Command()
const file = currentDirectory.findFile(name, extension); const file = currentDirectory.findFile(name, extension);
if (!file) if (!file)
return formatError(this.name, `${args[0]}: No such file`); return formatError((this as Command).name, `${args[0]}: No such file`);
file.delete(); file.delete();
return { blank: true }; return { blank: true };

View file

@ -1,4 +1,4 @@
import { VirtualFile } from "../../../virtual-drive/file/virtualFile"; import { VirtualFile } from "../../../virtual-drive/file";
import { formatError } from "../_utils/terminal.utils"; import { formatError } from "../_utils/terminal.utils";
import Command from "../command"; import Command from "../command";
@ -12,7 +12,7 @@ export const touch = new Command()
}) })
.setExecute(function(args, { currentDirectory }) { .setExecute(function(args, { currentDirectory }) {
if (args[0] === "girls\\" && args[1] === "boo**") if (args[0] === "girls\\" && args[1] === "boo**")
return formatError(this.name, "Cannot touch 'girls boo**': Permission denied"); return formatError((this as Command).name, "Cannot touch 'girls boo**': Permission denied");
const { name, extension } = VirtualFile.convertId(args[0]); const { name, extension } = VirtualFile.convertId(args[0]);

View file

@ -1,4 +1,4 @@
import { VirtualFile } from "../virtual-drive/file/virtualFile"; import { VirtualFile } from "../virtual-drive/file";
import { VirtualRoot } from "../virtual-drive/root/virtualRoot"; import { VirtualRoot } from "../virtual-drive/root/virtualRoot";
const PARENT_NODE = "options"; const PARENT_NODE = "options";

View file

@ -0,0 +1,2 @@
export { VirtualFile } from "./virtualFile";
export { VirtualFileLink } from "./virtualFileLink";

View file

@ -1,4 +1,5 @@
import { VirtualFile, VirtualFileJson } from "./virtualFile"; import { VirtualFile } from ".";
import { VirtualFileJson } from "./virtualFile";
export interface VirtualFileLinkJson extends VirtualFileJson { export interface VirtualFileLinkJson extends VirtualFileJson {
lnk: string; lnk: string;

View file

@ -2,10 +2,10 @@ import { APPS } from "../../../config/apps.config";
import AppsManager from "../../apps/appsManager"; import AppsManager from "../../apps/appsManager";
import { removeFromArray } from "../../_utils/array.utils"; import { removeFromArray } from "../../_utils/array.utils";
import WindowsManager from "../../windows/windowsManager"; import WindowsManager from "../../windows/windowsManager";
import { VirtualFileLink } from "../file/virtualFileLink"; import { VirtualFileJson } from "../file/virtualFile";
import { VirtualBase, VirtualBaseJson } from "../virtualBase"; import { VirtualBase, VirtualBaseJson } from "../virtualBase";
import { VirtualFile, VirtualFileJson } from "../file/virtualFile";
import { VirtualFolderLink } from "."; import { VirtualFolderLink } from ".";
import { VirtualFile, VirtualFileLink } from "../file";
export interface VirtualFolderJson extends VirtualBaseJson { export interface VirtualFolderJson extends VirtualBaseJson {
fls?: VirtualFileJson[]; fls?: VirtualFileJson[];

View file

@ -1,7 +1,7 @@
import { APPS } from "../../../config/apps.config"; import { APPS } from "../../../config/apps.config";
import { WALLPAPERS } from "../../../config/desktop.config"; import { WALLPAPERS } from "../../../config/desktop.config";
import AppsManager from "../../apps/appsManager"; import AppsManager from "../../apps/appsManager";
import { VirtualFileLink } from "../file/virtualFileLink"; import { VirtualFileLink } from "../file";
import { VirtualFolderLink } from "../folder"; import { VirtualFolderLink } from "../folder";
import { VirtualRoot } from "./virtualRoot"; import { VirtualRoot } from "./virtualRoot";

View file

@ -1,10 +1,11 @@
import { StorageManager } from "../../storage/storageManager"; import { StorageManager } from "../../storage/storageManager";
import { VirtualFolderLink, VirtualFolderLinkJson } from "../folder/virtualFolderLink"; import { VirtualFolderLink, VirtualFolderLinkJson } from "../folder/virtualFolderLink";
import { loadDefaultData } from "./defaultData"; import { loadDefaultData } from "./defaultData";
import { VirtualFile, VirtualFileJson } from "../file/virtualFile"; import { VirtualFileJson } from "../file/virtualFile";
import { VirtualFolder } from "../folder"; import { VirtualFolder } from "../folder";
import { VirtualFileLink, VirtualFileLinkJson } from "../file/virtualFileLink"; import { VirtualFileLinkJson } from "../file/virtualFileLink";
import { VirtualFolderJson } from "../folder/virtualFolder"; import { VirtualFolderJson } from "../folder/virtualFolder";
import { VirtualFile, VirtualFileLink } from "../file";
export interface VirtualRootJson extends VirtualFolderJson { export interface VirtualRootJson extends VirtualFolderJson {
scs: Record<string, string>; scs: Record<string, string>;

View file

@ -2,7 +2,7 @@ import { APPS } from "../../config/apps.config";
import AppsManager from "../apps/appsManager"; import AppsManager from "../apps/appsManager";
import { EventEmitter, EventNamesMap } from "../_utils/event.utils"; import { EventEmitter, EventNamesMap } from "../_utils/event.utils";
import { VirtualRoot } from "./root/virtualRoot"; import { VirtualRoot } from "./root/virtualRoot";
import { VirtualFile } from "./file/virtualFile"; import { VirtualFile } from "./file";
import { VirtualFolder } from "./folder"; import { VirtualFolder } from "./folder";
export interface VirtualBaseJson { export interface VirtualBaseJson {

View file

@ -5,7 +5,7 @@ import AppsManager from "../apps/appsManager";
import { randomRange } from "../math/random"; import { randomRange } from "../math/random";
import Vector2 from "../math/vector2"; import Vector2 from "../math/vector2";
import { TrackingManager } from "../tracking/trackingManager"; import { TrackingManager } from "../tracking/trackingManager";
import { VirtualFile } from "../virtual-drive/file/virtualFile"; import { VirtualFile } from "../virtual-drive/file";
export interface WindowOptions { export interface WindowOptions {
id?: string; id?: string;

View file

@ -0,0 +1,46 @@
import { APPS } from "../config/apps.config";
import { BASE_URL } from "../config/branding.config";
import { WALLPAPERS } from "../config/desktop.config";
import fs from "node:fs";
const PATH_TO_SITEMAP = "public/sitemap.xml";
function generateSitemap() {
const date = new Date();
const lastModified = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
const images = WALLPAPERS.map((path) => `
<image:image>
<image:loc>${BASE_URL.slice(0, -1) + path}</image:loc>
</image:image>`
);
const pages = Object.values(APPS).map((appId) => `
<url>
<loc>${BASE_URL + appId}</loc>
<lastmod>${lastModified}</lastmod>
</url>`
);
const sitemap = `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>${BASE_URL}</loc>
<lastmod>${lastModified}</lastmod>
${images.join("")}
</url>
${pages.join("")}
</urlset>`;
return sitemap.trim();
}
try {
fs.writeFileSync(PATH_TO_SITEMAP, generateSitemap());
console.log("Succesfully updated sitemap.xml");
} catch (error) {
console.error(error);
}

View file

@ -35,5 +35,10 @@
"./build", "./build",
"./dist", "./dist",
"./.vscode" "./.vscode"
] ],
"ts-node": {
"experimentalSpecifierResolution": "node",
"transpileOnly": true,
"esm": true,
}
} }