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-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",

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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";

View file

@ -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 {

View file

@ -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";

View file

@ -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 {

View file

@ -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";

View file

@ -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";

View file

@ -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, "/");

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 { 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}
>

View file

@ -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(() => {

View file

@ -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;

View file

@ -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";

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 TAG_LINE = "Web-based Operating System";
export const BASE_URL = "https://os.prozilla.dev/";
export const ASCII_LOGO = `
:.

View file

@ -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) {

View file

@ -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 {

View file

@ -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)

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 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")) {

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 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 };

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 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]);

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";
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 {
lnk: string;

View file

@ -1,2 +1,2 @@
export { VirtualFolder } from "./virtualFolder";
export { VirtualFolderLink } from "./virtualFolderLink";
export { VirtualFolderLink } from "./virtualFolderLink";

View file

@ -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[];

View file

@ -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";

View file

@ -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>;

View file

@ -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 {

View file

@ -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;

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",
"./dist",
"./.vscode"
]
],
"ts-node": {
"experimentalSpecifierResolution": "node",
"transpileOnly": true,
"esm": true,
}
}