Added router
This commit is contained in:
parent
a369a20701
commit
14015ce28e
39 changed files with 405 additions and 87 deletions
141
package-lock.json
generated
141
package-lock.json
generated
|
|
@ -44,6 +44,7 @@
|
|||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"gh-pages": "^5.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.8.0",
|
||||
"web-vitals": "^4.0.1"
|
||||
|
|
@ -513,6 +514,28 @@
|
|||
"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": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
|
||||
|
|
@ -1800,6 +1823,30 @@
|
|||
"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": {
|
||||
"version": "1.0.5",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
|
|
@ -2171,6 +2227,12 @@
|
|||
"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": {
|
||||
"version": "1.0.1",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
|
@ -2692,6 +2760,15 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
|
@ -4575,6 +4652,12 @@
|
|||
"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": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.2.1.tgz",
|
||||
|
|
@ -5788,6 +5871,49 @@
|
|||
"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": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
|
||||
|
|
@ -5985,6 +6111,12 @@
|
|||
"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": {
|
||||
"version": "5.2.12",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@
|
|||
"start": "vite --port 3000 --host",
|
||||
"build": "tsc && vite build",
|
||||
"serve": "vite preview",
|
||||
"predeploy": "npm run build",
|
||||
"deploy": "sh deploy.sh"
|
||||
"predeploy": "npm run sitemap && npm run build",
|
||||
"deploy": "sh deploy.sh",
|
||||
"sitemap": "node --experimental-specifier-resolution=node --loader ts-node/esm ./src/tools/sitemapGenerator.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"gh-pages": "^5.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.8.0",
|
||||
"web-vitals": "^4.0.1"
|
||||
|
|
|
|||
|
|
@ -4,38 +4,67 @@
|
|||
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
|
||||
<url>
|
||||
<loc>https://os.prozilla.dev/</loc>
|
||||
<lastmod>2024-6-9</lastmod>
|
||||
|
||||
<image:image>
|
||||
<image:loc>https://os.prozilla.dev/assets/banner-logo-title.png</image:loc>
|
||||
</image:image>
|
||||
<image:image>
|
||||
<image:loc>https://os.prozilla.dev/assets/screenshots/screenshot-files-info-taskbar-desktop.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/wallpapers/abstract-mesh-gradient-orange-red-purple.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/abstract-wallpaper-mesh-gradient-cyan.png</image:loc>
|
||||
</image:image>
|
||||
<image:image>
|
||||
<image:loc>https://os.prozilla.dev/assets/wallpapers/colorful-abstract-wallpaper-blue-red-green.png</image:loc>
|
||||
</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:loc>https://os.prozilla.dev/assets/wallpapers/mesh-gradient-wallpaper-red-purple.png</image:loc>
|
||||
</image:image>
|
||||
<image:image>
|
||||
<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/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: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/flame-abstract-wallpaper-orange.png</image:loc>
|
||||
</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>
|
||||
</urlset>
|
||||
10
src/App.tsx
10
src/App.tsx
|
|
@ -1,8 +1,4 @@
|
|||
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 { ZIndexManagerProvider } from "./hooks/z-index/zIndexManagerProvider";
|
||||
import { ThemeProvider } from "./hooks/themes/themes";
|
||||
|
|
@ -10,6 +6,7 @@ import { VirtualRootProvider } from "./hooks/virtual-drive/virtualRootProvider";
|
|||
import { WindowsManagerProvider } from "./hooks/windows/windowsManagerProvider";
|
||||
import { ModalsManagerProvider } from "./hooks/modals/modalsManagerProvider";
|
||||
import { SettingsManagerProvider } from "./hooks/settings/settingsManagerProvider";
|
||||
import { Router } from "./components/router/Router";
|
||||
|
||||
export default function App(): ReactElement {
|
||||
useEffect(() => {
|
||||
|
|
@ -31,10 +28,7 @@ export default function App(): ReactElement {
|
|||
<SettingsManagerProvider>
|
||||
<ThemeProvider>
|
||||
<div className={styles.App}>
|
||||
<Taskbar/>
|
||||
<WindowsView/>
|
||||
<ModalsView/>
|
||||
<Desktop/>
|
||||
<Router/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</SettingsManagerProvider>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import styles from "./Button.module.css";
|
||||
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 {
|
||||
className?: string;
|
||||
href?: string;
|
||||
icon?: IconProp;
|
||||
target?: HTMLAttributeAnchorTarget;
|
||||
children?: ReactNode;
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export function Button(props: ButtonProps) {
|
||||
let { className = "" } = props;
|
||||
const { href, children } = props;
|
||||
const { href, children, icon, target } = props;
|
||||
|
||||
className = `${styles.Button} ${className}`;
|
||||
|
||||
|
|
@ -21,14 +24,14 @@ export function Button(props: ButtonProps) {
|
|||
|
||||
return (<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
target={target ?? "_blank"}
|
||||
rel="noreferrer"
|
||||
tabIndex={0}
|
||||
{...props}
|
||||
className={className}
|
||||
>
|
||||
{children}
|
||||
<FontAwesomeIcon icon={faExternalLink}/>
|
||||
<FontAwesomeIcon icon={icon ?? faExternalLink}/>
|
||||
</a>);
|
||||
} else {
|
||||
return (<button
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import { CODE_FORMATS } from "../../../config/apps/textEditor.config";
|
|||
import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config";
|
||||
import { WindowProps } from "../../windows/WindowView";
|
||||
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 ImportButton from "./ImportButton";
|
||||
import { useAlert } from "../../../hooks/modals/alert";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { FormEventHandler, ReactElement } from "react";
|
|||
import styles from "./FileExplorer.module.css";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
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";
|
||||
|
||||
interface ImportButtonProps {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 { Interactable } from "../../../_utils/interactable/Interactable";
|
||||
import styles from "./DirectoryList.module.css";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useWindowsManager } from "../../../hooks/windows/windowsManagerContext"
|
|||
import styles from "./MediaViewer.module.css";
|
||||
import { APPS } from "../../../config/apps.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";
|
||||
|
||||
interface MediaViewerProps extends WindowProps {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { FileSelector } from "../../../modals/file-selector/FileSelector";
|
|||
import { SELECTOR_MODE } from "../../../../config/apps/fileExplorer.config";
|
||||
import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../../config/modals.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 { THEMES } from "../../../../config/themes.config";
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { useWindowedModal } from "../../../hooks/modals/windowedModal";
|
|||
import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../config/modals.config";
|
||||
import { FileSelector } from "../../modals/file-selector/FileSelector";
|
||||
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 { DropdownAction } from "../../actions/actions/DropdownAction";
|
||||
import { ClickAction } from "../../actions/actions/ClickAction";
|
||||
|
|
|
|||
|
|
@ -1,19 +1,11 @@
|
|||
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";
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {VirtualFile} props.currentFile
|
||||
* @param {string} props.src
|
||||
* @param {string} props.alt
|
||||
* @param {ModalsManager} props.modalsManager
|
||||
* @param {WindowsManager} props.windowsManager
|
||||
* @param {App} props.app
|
||||
*/
|
||||
export function MarkdownImage({ currentFile, alt, src, modalsManager, windowsManager, app, ...props }) {
|
||||
interface MarkdownImageProps {
|
||||
src: string;
|
||||
alt: string
|
||||
}
|
||||
|
||||
export function MarkdownImage({ alt, src, ...props }: MarkdownImageProps) {
|
||||
const source = useMemo(() => {
|
||||
if (src.startsWith("public")) {
|
||||
return src.replace(/^public\//g, "/");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useMemo } from "react";
|
||||
import { MouseEventHandler, ReactNode, useMemo } from "react";
|
||||
import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useContextMenu } from "../../../../hooks/modals/contextMenu";
|
||||
import { Actions } from "../../../actions/Actions";
|
||||
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 AppsManager from "../../../../features/apps/appsManager";
|
||||
import App from "../../../../features/apps/app";
|
||||
|
|
@ -13,19 +13,19 @@ import Vector2 from "../../../../features/math/vector2";
|
|||
import WindowsManager from "../../../../features/windows/windowsManager";
|
||||
import { APPS } from "../../../../config/apps.config";
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {string} props.href
|
||||
* @param {*} props.children
|
||||
* @param {WindowsManager} props.windowsManager
|
||||
* @param {Function} props.setCurrentFile
|
||||
* @param {VirtualFile} props.currentFile
|
||||
* @param {App} props.app
|
||||
*/
|
||||
export function MarkdownLink({ href, children, windowsManager, currentFile, setCurrentFile, app, ...props }) {
|
||||
interface MarkdownLinkProps {
|
||||
href: string;
|
||||
children: ReactNode;
|
||||
windowsManager: WindowsManager;
|
||||
setCurrentFile: Function;
|
||||
currentFile: VirtualFile;
|
||||
app: App;
|
||||
}
|
||||
|
||||
export function MarkdownLink({ href, children, windowsManager, currentFile, setCurrentFile, app, ...props }: MarkdownLinkProps) {
|
||||
const { openWindowedModal } = useWindowedModal();
|
||||
|
||||
const onClick = (event) => {
|
||||
const onClick = (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!href.startsWith("http://") && !href.startsWith("https://")) {
|
||||
|
|
@ -59,8 +59,8 @@ export function MarkdownLink({ href, children, windowsManager, currentFile, setC
|
|||
</Actions>
|
||||
});
|
||||
|
||||
const title = useMemo(() => {
|
||||
let title = null;
|
||||
const title = useMemo<string>(() => {
|
||||
let title: string = null;
|
||||
try {
|
||||
title = new URL(href).hostname;
|
||||
} catch (error) {
|
||||
|
|
@ -74,7 +74,7 @@ export function MarkdownLink({ href, children, windowsManager, currentFile, setC
|
|||
rel="noreferrer"
|
||||
href={href}
|
||||
onContextMenu={onContextMenu}
|
||||
onClick={onClick}
|
||||
onClick={onClick as unknown as MouseEventHandler}
|
||||
{...props}
|
||||
title={title}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import { Share } from "../modals/share/Share";
|
|||
import ModalsManager from "../../features/modals/modalsManager";
|
||||
import { VirtualFolder } from "../../features/virtual-drive/folder/virtualFolder";
|
||||
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";
|
||||
|
||||
export const Desktop = memo(() => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import utilStyles from "../../../styles/utils.module.css";
|
|||
import { StorageManager } from "../../../features/storage/storageManager";
|
||||
import AppsManager from "../../../features/apps/appsManager";
|
||||
import { ModalProps } from "../ModalView.js";
|
||||
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../../../features/virtual-drive/file";
|
||||
|
||||
interface FilePropetiesProps extends ModalProps {
|
||||
file: VirtualFile;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Button } from "../../_utils/button/Button";
|
|||
import { FileExplorer } from "../../apps/file-explorer/FileExplorer";
|
||||
import { WindowedModal } from "../_utils/WindowedModal";
|
||||
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 { VirtualFolder } from "../../../features/virtual-drive/folder";
|
||||
|
||||
|
|
|
|||
20
src/components/router/Router.tsx
Normal file
20
src/components/router/Router.tsx
Normal 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>;
|
||||
}
|
||||
30
src/components/router/routes/AppRoute.tsx
Normal file
30
src/components/router/routes/AppRoute.tsx
Normal 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}
|
||||
/>;
|
||||
}
|
||||
13
src/components/router/routes/DefaultRoute.tsx
Normal file
13
src/components/router/routes/DefaultRoute.tsx
Normal 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/>
|
||||
</>;
|
||||
}
|
||||
23
src/components/router/routes/NoRoute.module.css
Normal file
23
src/components/router/routes/NoRoute.module.css
Normal 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);
|
||||
}
|
||||
11
src/components/router/routes/NoRoute.tsx
Normal file
11
src/components/router/routes/NoRoute.tsx
Normal 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>;
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import { ANSI } from "./apps/terminal.config";
|
|||
|
||||
export const NAME = "ProzillaOS";
|
||||
export const TAG_LINE = "Web-based Operating System";
|
||||
export const BASE_URL = "https://os.prozilla.dev/";
|
||||
|
||||
export const ASCII_LOGO = `
|
||||
:.
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ export function isValidUrl(string: string): boolean {
|
|||
|
||||
export function setViewportTitle(title: string) {
|
||||
document.title = title;
|
||||
|
||||
document.querySelectorAll("meta[property='og:title'], meta[name='twitter:title']")?.forEach((element) => {
|
||||
element.setAttribute("content", title);
|
||||
});
|
||||
}
|
||||
|
||||
export function setViewportIcon(url: string) {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default class AppsManager {
|
|||
new App(APP_NAMES.BROWSER, APPS.BROWSER, Browser, {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ export default class Command {
|
|||
}
|
||||
|
||||
getOption(key: string): Option {
|
||||
let matchingOption = null;
|
||||
let matchingOption: Option = null;
|
||||
|
||||
this.options.forEach((option) => {
|
||||
if (option.short === key || option.long === key)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { VirtualFile } from "../../../virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../../../virtual-drive/file";
|
||||
import { formatError } from "../_utils/terminal.utils";
|
||||
import Command from "../command";
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ export const cat = new Command()
|
|||
const file = currentDirectory.findFile(name, extension);
|
||||
|
||||
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 (!options.includes("e")) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { VirtualFile } from "../../../virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../../../virtual-drive/file";
|
||||
import { formatError } from "../_utils/terminal.utils";
|
||||
import Command from "../command";
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ export const rm = new Command()
|
|||
const file = currentDirectory.findFile(name, extension);
|
||||
|
||||
if (!file)
|
||||
return formatError(this.name, `${args[0]}: No such file`);
|
||||
return formatError((this as Command).name, `${args[0]}: No such file`);
|
||||
|
||||
file.delete();
|
||||
return { blank: true };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { VirtualFile } from "../../../virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../../../virtual-drive/file";
|
||||
import { formatError } from "../_utils/terminal.utils";
|
||||
import Command from "../command";
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ export const touch = new Command()
|
|||
})
|
||||
.setExecute(function(args, { currentDirectory }) {
|
||||
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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { VirtualFile } from "../virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../virtual-drive/file";
|
||||
import { VirtualRoot } from "../virtual-drive/root/virtualRoot";
|
||||
|
||||
const PARENT_NODE = "options";
|
||||
|
|
|
|||
2
src/features/virtual-drive/file/index.ts
Normal file
2
src/features/virtual-drive/file/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { VirtualFile } from "./virtualFile";
|
||||
export { VirtualFileLink } from "./virtualFileLink";
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { VirtualFile, VirtualFileJson } from "./virtualFile";
|
||||
import { VirtualFile } from ".";
|
||||
import { VirtualFileJson } from "./virtualFile";
|
||||
|
||||
export interface VirtualFileLinkJson extends VirtualFileJson {
|
||||
lnk: string;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
export { VirtualFolder } from "./virtualFolder";
|
||||
export { VirtualFolderLink } from "./virtualFolderLink";
|
||||
export { VirtualFolderLink } from "./virtualFolderLink";
|
||||
|
|
@ -2,10 +2,10 @@ import { APPS } from "../../../config/apps.config";
|
|||
import AppsManager from "../../apps/appsManager";
|
||||
import { removeFromArray } from "../../_utils/array.utils";
|
||||
import WindowsManager from "../../windows/windowsManager";
|
||||
import { VirtualFileLink } from "../file/virtualFileLink";
|
||||
import { VirtualFileJson } from "../file/virtualFile";
|
||||
import { VirtualBase, VirtualBaseJson } from "../virtualBase";
|
||||
import { VirtualFile, VirtualFileJson } from "../file/virtualFile";
|
||||
import { VirtualFolderLink } from ".";
|
||||
import { VirtualFile, VirtualFileLink } from "../file";
|
||||
|
||||
export interface VirtualFolderJson extends VirtualBaseJson {
|
||||
fls?: VirtualFileJson[];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { APPS } from "../../../config/apps.config";
|
||||
import { WALLPAPERS } from "../../../config/desktop.config";
|
||||
import AppsManager from "../../apps/appsManager";
|
||||
import { VirtualFileLink } from "../file/virtualFileLink";
|
||||
import { VirtualFileLink } from "../file";
|
||||
import { VirtualFolderLink } from "../folder";
|
||||
import { VirtualRoot } from "./virtualRoot";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { StorageManager } from "../../storage/storageManager";
|
||||
import { VirtualFolderLink, VirtualFolderLinkJson } from "../folder/virtualFolderLink";
|
||||
import { loadDefaultData } from "./defaultData";
|
||||
import { VirtualFile, VirtualFileJson } from "../file/virtualFile";
|
||||
import { VirtualFileJson } from "../file/virtualFile";
|
||||
import { VirtualFolder } from "../folder";
|
||||
import { VirtualFileLink, VirtualFileLinkJson } from "../file/virtualFileLink";
|
||||
import { VirtualFileLinkJson } from "../file/virtualFileLink";
|
||||
import { VirtualFolderJson } from "../folder/virtualFolder";
|
||||
import { VirtualFile, VirtualFileLink } from "../file";
|
||||
|
||||
export interface VirtualRootJson extends VirtualFolderJson {
|
||||
scs: Record<string, string>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { APPS } from "../../config/apps.config";
|
|||
import AppsManager from "../apps/appsManager";
|
||||
import { EventEmitter, EventNamesMap } from "../_utils/event.utils";
|
||||
import { VirtualRoot } from "./root/virtualRoot";
|
||||
import { VirtualFile } from "./file/virtualFile";
|
||||
import { VirtualFile } from "./file";
|
||||
import { VirtualFolder } from "./folder";
|
||||
|
||||
export interface VirtualBaseJson {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import AppsManager from "../apps/appsManager";
|
|||
import { randomRange } from "../math/random";
|
||||
import Vector2 from "../math/vector2";
|
||||
import { TrackingManager } from "../tracking/trackingManager";
|
||||
import { VirtualFile } from "../virtual-drive/file/virtualFile";
|
||||
import { VirtualFile } from "../virtual-drive/file";
|
||||
|
||||
export interface WindowOptions {
|
||||
id?: string;
|
||||
|
|
|
|||
46
src/tools/sitemapGenerator.ts
Normal file
46
src/tools/sitemapGenerator.ts
Normal 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);
|
||||
}
|
||||
|
|
@ -35,5 +35,10 @@
|
|||
"./build",
|
||||
"./dist",
|
||||
"./.vscode"
|
||||
]
|
||||
],
|
||||
"ts-node": {
|
||||
"experimentalSpecifierResolution": "node",
|
||||
"transpileOnly": true,
|
||||
"esm": true,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue