Added linting rules + updated docs

This commit is contained in:
Prozilla 2023-08-06 13:35:21 +02:00
parent 6f990ba66a
commit e223747795
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
35 changed files with 298 additions and 99 deletions

View file

@ -33,6 +33,10 @@
2. Run `npm run deploy` - This will create a new build by running the redeploy script, add a CNAME pointing to your domain and then push the build folder to a branch called `gh-pages`. 2. Run `npm run deploy` - This will create a new build by running the redeploy script, add a CNAME pointing to your domain and then push the build folder to a branch called `gh-pages`.
3. Configure your GitHub Pages to deploy the `gh-pages` branch to your domain. 3. Configure your GitHub Pages to deploy the `gh-pages` branch to your domain.
Once the initial setup is complete, you can simply run `npm run deploy` and your website will be built and deployed to GitHub Pages.
> Note: When the deployment process is complete, you won't see the changes reflected on your website until a few moments later. This is because GitHub Pages needs to run its own build step before the website updates. You can view details about this process in the Actions tab on GitHub.
### Structure ### Structure
- [src](../src) directory - [src](../src) directory

View file

@ -4,6 +4,8 @@
Most code for features can be found in the [features](../../src/features) directory. This directory is a library that is mostly used by files in the [components](../../src/components) and [hooks](../../src/hooks) directory. Most code for features can be found in the [features](../../src/features) directory. This directory is a library that is mostly used by files in the [components](../../src/components) and [hooks](../../src/hooks) directory.
> Note: Inside this part of the docs you will often see mentions of directories like `features` or `components`. These paths are relative to the `src` directory. The respective paths relative to the root of this project are `src/features` and `src/components`.
## Table of Contents ## Table of Contents
- [Applications](applications/README.md) - [Applications](applications/README.md)

114
package-lock.json generated
View file

@ -27,6 +27,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"eslint-plugin-jsdoc": "^46.4.6",
"gh-pages": "^5.0.0" "gh-pages": "^5.0.0"
} }
}, },
@ -2315,6 +2316,20 @@
"postcss-selector-parser": "^6.0.10" "postcss-selector-parser": "^6.0.10"
} }
}, },
"node_modules/@es-joy/jsdoccomment": {
"version": "0.40.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz",
"integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==",
"dev": true,
"dependencies": {
"comment-parser": "1.4.0",
"esquery": "^1.5.0",
"jsdoc-type-pratt-parser": "~4.0.0"
},
"engines": {
"node": ">=16"
}
},
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@ -5154,6 +5169,15 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/are-docs-informative": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
"integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/arg": { "node_modules/arg": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@ -6136,6 +6160,15 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/comment-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz",
"integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==",
"dev": true,
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/common-path-prefix": { "node_modules/common-path-prefix": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
@ -7556,6 +7589,41 @@
} }
} }
}, },
"node_modules/eslint-plugin-jsdoc": {
"version": "46.4.6",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz",
"integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==",
"dev": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.40.1",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.0",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
"esquery": "^1.5.0",
"is-builtin-module": "^3.2.1",
"semver": "^7.5.4",
"spdx-expression-parse": "^3.0.1"
},
"engines": {
"node": ">=16"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-jsx-a11y": { "node_modules/eslint-plugin-jsx-a11y": {
"version": "6.7.1", "version": "6.7.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
@ -9517,6 +9585,21 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-builtin-module": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
"dev": true,
"dependencies": {
"builtin-modules": "^3.3.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-callable": { "node_modules/is-callable": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@ -11923,6 +12006,15 @@
"js-yaml": "bin/js-yaml.js" "js-yaml": "bin/js-yaml.js"
} }
}, },
"node_modules/jsdoc-type-pratt-parser": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
"integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
"dev": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/jsdom": { "node_modules/jsdom": {
"version": "16.7.0", "version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@ -15735,6 +15827,28 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"deprecated": "Please use @jridgewell/sourcemap-codec instead" "deprecated": "Please use @jridgewell/sourcemap-codec instead"
}, },
"node_modules/spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"dev": true
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/spdx-license-ids": {
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
"integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
"dev": true
},
"node_modules/spdy": { "node_modules/spdy": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",

View file

@ -35,7 +35,37 @@
"extends": [ "extends": [
"react-app", "react-app",
"react-app/jest" "react-app/jest"
] ],
"plugins": [
"jsdoc"
],
"rules": {
"indent": ["error", "tab", { "SwitchCase": 1 }],
"jsdoc/no-undefined-types": "warn",
"jsdoc/require-param": "warn",
"jsdoc/check-tag-names": "warn",
"jsdoc/check-types": ["warn", {}],
"jsdoc/check-values": "warn",
"jsdoc/empty-tags": "warn",
"jsdoc/check-param-names": "warn",
"jsdoc/check-property-names": "warn",
"jsdoc/check-access": "warn",
"jsdoc/check-alignment": "warn",
"jsdoc/multiline-blocks": "warn",
"jsdoc/no-blank-block-descriptions": "warn",
"jsdoc/require-hyphen-before-param-description": "warn"
},
"settings": {
"jsdoc": {
"preferredTypes": {
"Object":"object",
"object.<>":"Object<>",
"Object.<>":"Object<>",
"object<>":"Object<>"
}
}
}
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -51,6 +81,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"eslint-plugin-jsdoc": "^46.4.6",
"gh-pages": "^5.0.0" "gh-pages": "^5.0.0"
} }
} }

View file

@ -6,8 +6,8 @@ import styles from "./HeaderMenu.module.css";
/** /**
* @param {Object} props * @param {Object} props
* @param {Object<String, Object<String, Function>>} props.options * @param {Object<String, Object<string, function>>} props.options
* @param {Object<String, Object<String, Array<String>>>} props.shortcuts * @param {Object<String, Object<string, string[]>>} props.shortcuts
*/ */
export function HeaderMenu({ options, shortcuts }) { export function HeaderMenu({ options, shortcuts }) {
const [activeKeys, setActiveKeys] = useState([]); const [activeKeys, setActiveKeys] = useState([]);

View file

@ -8,7 +8,7 @@ import { VirtualFile } from "../../../features/virtual-drive/virtual-file.js";
import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.js"; import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.js";
/** /**
* @param {Object} props * @param {object} props
* @param {VirtualFile} props.file * @param {VirtualFile} props.file
*/ */
function FilePreview({ file }) { function FilePreview({ file }) {

View file

@ -4,10 +4,9 @@ import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.
import styles from "./MediaViewer.module.css"; import styles from "./MediaViewer.module.css";
/** /**
* * @param {object} props
* @param {Object} props
* @param {VirtualFile} props.file * @param {VirtualFile} props.file
* @returns * @param {Function} props.close
*/ */
export function MediaViewer({ file, close }) { export function MediaViewer({ file, close }) {
const windowsManager = useWindowsManager(); const windowsManager = useWindowsManager();

View file

@ -9,7 +9,7 @@ import { SettingsManager } from "../../../features/settings/settings.js";
import { VirtualRoot } from "../../../features/virtual-drive/virtual-root.js"; import { VirtualRoot } from "../../../features/virtual-drive/virtual-root.js";
/** /**
* @param {Object} props * @param {object} props
* @param {VirtualRoot} props.virtualRoot * @param {VirtualRoot} props.virtualRoot
* @param {SettingsManager} props.settingsManager * @param {SettingsManager} props.settingsManager
*/ */

View file

@ -7,8 +7,8 @@ const USERNAME = "user";
const HOSTNAME = "prozilla-os"; const HOSTNAME = "prozilla-os";
/** /**
* @param {Object} props * @param {object} props
* @param {String} props.text * @param {string} props.text
*/ */
function OutputLine({ text }) { function OutputLine({ text }) {
return ( return (
@ -17,9 +17,9 @@ function OutputLine({ text }) {
} }
/** /**
* @param {Object} props * @param {object} props
* @param {String} props.value * @param {string} props.value
* @param {String} props.prefix * @param {string} props.prefix
* @param {Function} props.onChange * @param {Function} props.onChange
* @param {Function} props.onKeyUp * @param {Function} props.onKeyUp
* @param {Function} props.onKeyDown * @param {Function} props.onKeyDown

View file

@ -9,8 +9,11 @@ const defaultZoom = 16;
const zoomSpeed = 4; const zoomSpeed = 4;
/** /**
* @param {Object} props * @param {object} props
* @param {VirtualFile} props.file * @param {VirtualFile} props.file
* @param {Function} props.setTitle
* @param {Function} props.close
* @param {string} props.mode
*/ */
export function TextEditor({ file, setTitle, close, mode }) { export function TextEditor({ file, setTitle, close, mode }) {
const [currentFile, setCurrentFile] = useState(file); const [currentFile, setCurrentFile] = useState(file);

View file

@ -6,7 +6,6 @@ import ApplicationsManager from "../../features/applications/applications.js";
import { useWindows } from "../../hooks/windows/WindowsContext.js"; import { useWindows } from "../../hooks/windows/WindowsContext.js";
import { useWindowsManager } from "../../hooks/windows/WindowsManagerContext.js"; import { useWindowsManager } from "../../hooks/windows/WindowsManagerContext.js";
import { ReactSVG } from "react-svg"; import { ReactSVG } from "react-svg";
// eslint-disable-next-line no-unused-vars
import Application from "../../features/applications/application.js"; import Application from "../../features/applications/application.js";
import { HomeMenu } from "./menus/HomeMenu.jsx"; import { HomeMenu } from "./menus/HomeMenu.jsx";
import OutsideClickListener from "../../hooks/utils/outsideClick.js"; import OutsideClickListener from "../../hooks/utils/outsideClick.js";
@ -18,7 +17,7 @@ import { Calendar } from "./indicators/Calendar.jsx";
import { useScrollWithShadow } from "../../hooks/utils/scrollWithShadows.js"; import { useScrollWithShadow } from "../../hooks/utils/scrollWithShadows.js";
/** /**
* @param {Object} props * @param {object} props
* @param {Application} props.app * @param {Application} props.app
*/ */
function AppButton({ app }) { function AppButton({ app }) {
@ -96,7 +95,7 @@ export function Taskbar() {
const search = (query) => { const search = (query) => {
updateShowSearch(true); updateShowSearch(true);
} };
return ( return (
<div className={styles["Task-bar"]}> <div className={styles["Task-bar"]}>

View file

@ -9,6 +9,12 @@ import { closeTab } from "../../../features/utils/browser.js";
import { useKeyboardListener } from "../../../hooks/utils/keyboard.js"; import { useKeyboardListener } from "../../../hooks/utils/keyboard.js";
import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js"; import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js";
/**
* @param {object} props
* @param {boolean} props.active
* @param {Function} props.setActive
* @param {Function} props.search
*/
export function HomeMenu({ active, setActive, search }) { export function HomeMenu({ active, setActive, search }) {
const windowsManager = useWindowsManager(); const windowsManager = useWindowsManager();
const virtualRoot = useVirtualRoot(); const virtualRoot = useVirtualRoot();

View file

@ -6,6 +6,14 @@ import { ReactSVG } from "react-svg";
import { useEffect } from "react"; import { useEffect } from "react";
import { useState } from "react"; import { useState } from "react";
/**
* @param {object} props
* @param {boolean} props.active
* @param {Function} props.setActive
* @param {string} props.searchQuery
* @param {Function} props.setSearchQuery
* @param {import("react").ElementRef} props.inputRef
*/
export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inputRef }) { export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inputRef }) {
const windowsManager = useWindowsManager(); const windowsManager = useWindowsManager();
const [apps, setApps] = useState(null); const [apps, setApps] = useState(null);

View file

@ -4,9 +4,10 @@ import OutsideClickListener from "../../hooks/utils/outsideClick.js";
import { formatShortcut } from "../../features/utils/string.js"; import { formatShortcut } from "../../features/utils/string.js";
/** /**
* @param {Object} props * @param {object} props
* @param {String} props.label * @param {string} props.label
* @param {Object.<string, Function>} props.options * @param {Object<string, Function>} props.options
* @param {Object<string, string[]>} props.shortcuts
*/ */
export function DropdownButton({ label, options, shortcuts }) { export function DropdownButton({ label, options, shortcuts }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -33,7 +34,7 @@ export function DropdownButton({ label, options, shortcuts }) {
)} )}
</div>) </div>)
: null : null
} }
</div> </div>
</OutsideClickListener> </OutsideClickListener>
) )

View file

@ -12,13 +12,14 @@ import Application from "../../features/applications/application.js";
import Vector2 from "../../features/math/vector2.js"; import Vector2 from "../../features/math/vector2.js";
/** /**
* @param {Object} props * @param {object} props
* @param {String} props.id * @param {string} props.id
* @param {Application} props.app * @param {Application} props.app
* @param {Vector2} props.size * @param {Vector2} props.size
* @param {Vector2} props.position * @param {Vector2} props.position
* @param {boolean} props.focused * @param {boolean} props.focused
* @param {Function} props.onInteract * @param {Function} props.onInteract
* @param {object} props.options
*/ */
export function Window({ id, app, size, position, focused = false, onInteract, options }) { export function Window({ id, app, size, position, focused = false, onInteract, options }) {
const windowsManager = useWindowsManager(); const windowsManager = useWindowsManager();
@ -28,18 +29,18 @@ export function Window({ id, app, size, position, focused = false, onInteract, o
const [minimized, setMinimized] = useState(false); const [minimized, setMinimized] = useState(false);
const [screenWidth, setScreenWidth] = useState(100); const [screenWidth, setScreenWidth] = useState(100);
const [screenHeight, setScreenHeight] = useState(100); const [screenHeight, setScreenHeight] = useState(100);
const [title, setTitle] = useState(app.name); const [title, setTitle] = useState(app.name);
useEffect(() => { useEffect(() => {
const resizeObserver = new ResizeObserver((event) => { const resizeObserver = new ResizeObserver((event) => {
setScreenWidth(event[0].contentBoxSize[0].inlineSize); setScreenWidth(event[0].contentBoxSize[0].inlineSize);
setScreenHeight(event[0].contentBoxSize[0].blockSize); setScreenHeight(event[0].contentBoxSize[0].blockSize);
}); });
resizeObserver.observe(document.getElementById("root")); resizeObserver.observe(document.getElementById("root"));
}); });
const close = () => { const close = () => {
windowsManager.close(id); windowsManager.close(id);

View file

@ -1,9 +1,11 @@
import React from "react";
export default class Application { export default class Application {
/** /**
* @param {String} name * @param {string} name
* @param {String} id * @param {string} id
* @param {React.ReactElement} windowContent * @param {React.ReactElement} windowContent
* @param {Object|null} windowOptions - Default window options * @param {object | null} windowOptions - Default window options
*/ */
constructor(name, id, windowContent, windowOptions) { constructor(name, id, windowContent, windowOptions) {
Object.assign(this, { name, id, windowContent, windowOptions }); Object.assign(this, { name, id, windowContent, windowOptions });

View file

@ -22,7 +22,7 @@ export default class ApplicationsManager {
] ]
/** /**
* @param {String} id * @param {string} id
* @returns {Application} * @returns {Application}
*/ */
static getApplication(id) { static getApplication(id) {
@ -40,7 +40,7 @@ export default class ApplicationsManager {
/** /**
* Get the application associated with a file extension * Get the application associated with a file extension
* @param {String} fileExtension * @param {string} fileExtension
* @returns {Application} * @returns {Application}
*/ */
static getFileApplication(fileExtension) { static getFileApplication(fileExtension) {

View file

@ -1,6 +1,6 @@
export class Command { export class Command {
/** /**
* @param {String} name * @param {string} name
* @param {Function} execute * @param {Function} execute
*/ */
constructor(name, execute) { constructor(name, execute) {

View file

@ -1,3 +1,8 @@
/**
* @param {number} min
* @param {number} max
* @returns {number}
*/
export function randomRange(min, max) { export function randomRange(min, max) {
return Math.random() * (max - min) + min; return Math.random() * (max - min) + min;
} }

View file

@ -13,7 +13,7 @@ export class Settings {
/** /**
* @param {VirtualRoot} virtualRoot * @param {VirtualRoot} virtualRoot
* @param {String} path * @param {string} path
*/ */
constructor(virtualRoot, path) { constructor(virtualRoot, path) {
this.#virtualRoot = virtualRoot; this.#virtualRoot = virtualRoot;
@ -63,7 +63,7 @@ export class Settings {
/** /**
* Checks if xml doc is missing * Checks if xml doc is missing
* @returns {Promise<Boolean>} * @returns {Promise<boolean>}
*/ */
async isMissingXmlDoc() { async isMissingXmlDoc() {
if (this.xmlDoc == null) if (this.xmlDoc == null)
@ -74,14 +74,14 @@ export class Settings {
/** /**
* @callback valueCallback * @callback valueCallback
* @param {String} value * @param {string} value
*/ */
/** /**
* Gets a value by a given key if it exists or calls a callback function whenever the value changes * Gets a value by a given key if it exists or calls a callback function whenever the value changes
* @param {String} key * @param {string} key
* @param {valueCallback} callback * @param {valueCallback} callback
* @returns {Promise<String|null>} * @returns {Promise<string | null>}
*/ */
async get(key, callback) { async get(key, callback) {
if (await this.isMissingXmlDoc()) if (await this.isMissingXmlDoc())
@ -107,8 +107,8 @@ export class Settings {
} }
/** /**
* @param {String} key * @param {string} key
* @param {String} value * @param {string} value
*/ */
async set(key, value) { async set(key, value) {
if (await this.isMissingXmlDoc()) if (await this.isMissingXmlDoc())
@ -123,14 +123,14 @@ export class Settings {
export class SettingsManager { export class SettingsManager {
/** /**
* @type {Object<String, String>} * @type {Object<string, string>}
*/ */
static VIRTUAL_PATHS = { static VIRTUAL_PATHS = {
"desktop": "~/.config/desktop.xml" "desktop": "~/.config/desktop.xml"
}; };
/** /**
* @type {Object<String, Settings>} * @type {Object<string, Settings>}
*/ */
#pathToSettings = {}; #pathToSettings = {};
@ -151,7 +151,7 @@ export class SettingsManager {
} }
/** /**
* @param {String} path * @param {string} path
* @returns {Settings} * @returns {Settings}
*/ */
get(path) { get(path) {

View file

@ -1,3 +1,7 @@
/**
* @param {*} item
* @param {*[]} array
*/
export function removeFromArray(item, array) { export function removeFromArray(item, array) {
const index = array.indexOf(item); const index = array.indexOf(item);
if (index !== -1) { if (index !== -1) {

View file

@ -1,17 +1,17 @@
export class EventEmitter { export class EventEmitter {
/** /**
* @type {Object<String, String>} * @type {Object<string, string>}
*/ */
static EVENT_NAMES = {}; static EVENT_NAMES = {};
/** /**
* @type {Object<String, Array<Function>>} * @type {Object<string, Array<Function>>}
*/ */
#events = {} #events = {}
/** /**
* Add event listener for an event * Add event listener for an event
* @param {EVENT_NAMES} eventName * @param {EventEmitter.EVENT_NAMES} eventName
* @param {Function} callback * @param {Function} callback
*/ */
on(eventName, callback) { on(eventName, callback) {
@ -23,7 +23,7 @@ export class EventEmitter {
/** /**
* Remove event listener for an event * Remove event listener for an event
* @param {EVENT_NAMES} eventName * @param {string} eventName
* @param {Function} callback * @param {Function} callback
*/ */
off(eventName, callback) { off(eventName, callback) {
@ -36,7 +36,7 @@ export class EventEmitter {
/** /**
* Dispatch event * Dispatch event
* @param {EVENT_NAMES} eventName * @param {string} eventName
* @param {*} data * @param {*} data
*/ */
emit(eventName, data) { emit(eventName, data) {

View file

@ -1,3 +1,7 @@
/**
* @param {string[]} shortcut
* @returns {string}
*/
export function formatShortcut(shortcut) { export function formatShortcut(shortcut) {
const specialKeys = []; const specialKeys = [];
const singleKeys = []; const singleKeys = [];

View file

@ -4,7 +4,7 @@ import { VirtualRoot } from "./virtual-root.js";
export class VirtualBase extends EventEmitter { export class VirtualBase extends EventEmitter {
/** /**
* @param {String} name * @param {string} name
*/ */
constructor(name) { constructor(name) {
super(); super();
@ -16,7 +16,7 @@ export class VirtualBase extends EventEmitter {
} }
/** /**
* @param {String} name * @param {string} name
* @returns {VirtualBase} * @returns {VirtualBase}
*/ */
setName(name) { setName(name) {
@ -26,7 +26,7 @@ export class VirtualBase extends EventEmitter {
} }
/** /**
* @param {String} alias * @param {string} alias
* @returns {ThisType} * @returns {ThisType}
*/ */
setAlias(alias) { setAlias(alias) {

View file

@ -13,8 +13,8 @@ export class VirtualFile extends VirtualBase {
}; };
/** /**
* @param {String} name * @param {string} name
* @param {String=} extension * @param {string=} extension
*/ */
constructor(name, extension) { constructor(name, extension) {
super(name); super(name);
@ -22,7 +22,7 @@ export class VirtualFile extends VirtualBase {
} }
/** /**
* @param {String} alias * @param {string} alias
* @returns {VirtualFile} * @returns {VirtualFile}
*/ */
setAlias(alias) { setAlias(alias) {
@ -31,7 +31,7 @@ export class VirtualFile extends VirtualBase {
/** /**
* Sets the source of this file and removes the content * Sets the source of this file and removes the content
* @param {String} source * @param {string} source
* @returns {VirtualFile} * @returns {VirtualFile}
*/ */
setSource(source) { setSource(source) {
@ -46,7 +46,7 @@ export class VirtualFile extends VirtualBase {
/** /**
* Sets the content of this file and removes the source * Sets the content of this file and removes the source
* @param {String|*} content * @param {string | *} content
* @returns {VirtualFile} * @returns {VirtualFile}
*/ */
setContent(content) { setContent(content) {
@ -67,7 +67,7 @@ export class VirtualFile extends VirtualBase {
} }
/** /**
* @return {Promise<String|null>} * @returns {Promise<string | null>}
*/ */
async read() { async read() {
if (this.content != null) if (this.content != null)

View file

@ -12,8 +12,8 @@ export class VirtualFolder extends VirtualBase {
} }
/** /**
* @param {String} name * @param {string} name
* @param {Number} type * @param {number} type
*/ */
constructor(name, type) { constructor(name, type) {
super(name); super(name);
@ -23,7 +23,7 @@ export class VirtualFolder extends VirtualBase {
} }
/** /**
* @param {String} alias * @param {string} alias
* @returns {VirtualFolder} * @returns {VirtualFolder}
*/ */
setAlias(alias) { setAlias(alias) {
@ -32,8 +32,8 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Returns true if this folder contains a file matching a name and extension * Returns true if this folder contains a file matching a name and extension
* @param {String} name * @param {string} name
* @param {String} extension * @param {string} extension
* @returns {VirtualFile} * @returns {VirtualFile}
*/ */
hasFile(name, extension) { hasFile(name, extension) {
@ -42,7 +42,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Returns true if this folder contains a folder matching a name * Returns true if this folder contains a folder matching a name
* @param {String} name * @param {string} name
* @returns {boolean} * @returns {boolean}
*/ */
hasFolder(name) { hasFolder(name) {
@ -51,8 +51,8 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Finds and returns a file inside this folder matching a name and extension * Finds and returns a file inside this folder matching a name and extension
* @param {String} name * @param {string} name
* @param {String} extension * @param {string} extension
* @returns {VirtualFile} * @returns {VirtualFile}
*/ */
findFile(name, extension) { findFile(name, extension) {
@ -69,7 +69,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Finds and returns a folder inside this folder matching a name * Finds and returns a folder inside this folder matching a name
* @param {String} name * @param {string} name
* @returns {VirtualFolder} * @returns {VirtualFolder}
*/ */
findSubFolder(name) { findSubFolder(name) {
@ -91,8 +91,8 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Creates a file with a name and extension * Creates a file with a name and extension
* @param {String} name * @param {string} name
* @param {String} extension * @param {string} extension
* @param {createFileCallback} callback * @param {createFileCallback} callback
* @returns {VirtualFolder} * @returns {VirtualFolder}
*/ */
@ -107,9 +107,9 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Creates files based on an array of objects with file names and extensions * Creates files based on an array of objects with file names and extensions
* @param {Object[]} files * @param {object[]} files
* @param {String} Object[].name * @param {string} files.name
* @param {String} Object[].extension * @param {string} files.extension
* @returns {VirtualFolder} * @returns {VirtualFolder}
*/ */
createFiles(files) { createFiles(files) {
@ -127,7 +127,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Creates a folder with a name * Creates a folder with a name
* @param {String} name * @param {string} name
* @returns {VirtualFolder} * @returns {VirtualFolder}
* @param {createFolderCallback} callback * @param {createFolderCallback} callback
*/ */
@ -142,7 +142,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Creates folders based on an array of folder names * Creates folders based on an array of folder names
* @param {String[]} folders * @param {string[]} folders
* @returns {VirtualFolder} * @returns {VirtualFolder}
*/ */
createFolders(folders) { createFolders(folders) {
@ -156,7 +156,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Adds a file at a destination * Adds a file at a destination
* @deprecated * @deprecated
* @param {String} destination * @param {string} destination
*/ */
addFile(destination) { addFile(destination) {
const folderNames = destination.split("/"); const folderNames = destination.split("/");
@ -182,7 +182,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Adds a folder at a destination * Adds a folder at a destination
* @deprecated * @deprecated
* @param {String} destination * @param {string} destination
*/ */
addFolder(destination) { addFolder(destination) {
if (destination.endsWith("/")) if (destination.endsWith("/"))
@ -218,7 +218,7 @@ export class VirtualFolder extends VirtualBase {
/** /**
* Returns the file or folder at a relative path or null if it doesn't exist * Returns the file or folder at a relative path or null if it doesn't exist
* @param {String} relativePath * @param {string} relativePath
* @returns {VirtualFile|VirtualFolder|null} * @returns {VirtualFile|VirtualFolder|null}
*/ */
navigate(relativePath) { navigate(relativePath) {

View file

@ -170,7 +170,7 @@ export class VirtualRoot extends VirtualFolder {
/** /**
* Adds a shortcut to a file or folder * Adds a shortcut to a file or folder
* @param {String} name * @param {string} name
* @param {VirtualFile|VirtualFolder} destination * @param {VirtualFile|VirtualFolder} destination
* @returns {VirtualRoot} * @returns {VirtualRoot}
*/ */

View file

@ -11,9 +11,9 @@ export default class WindowsManager {
} }
/** /**
* @param {String} appId * @param {string} appId
* @param {Object|null} options * @param {object | null} options
* @returns {Object} * @returns {object}
*/ */
open(appId, options) { open(appId, options) {
const app = ApplicationsManager.getApplication(appId); const app = ApplicationsManager.getApplication(appId);
@ -45,7 +45,7 @@ export default class WindowsManager {
/** /**
* @param {VirtualFile} file * @param {VirtualFile} file
* @returns {Object} * @returns {object}
*/ */
openFile(file) { openFile(file) {
const app = ApplicationsManager.getFileApplication(file.extension); const app = ApplicationsManager.getFileApplication(file.extension);
@ -54,7 +54,7 @@ export default class WindowsManager {
} }
/** /**
* @param {String} windowId * @param {string} windowId
*/ */
close(windowId) { close(windowId) {
windowId = windowId.toString(); windowId = windowId.toString();
@ -72,7 +72,7 @@ export default class WindowsManager {
} }
/** /**
* @param {Object} window * @param {string} windowId
*/ */
focus(windowId) { focus(windowId) {
windowId = windowId.toString(); windowId = windowId.toString();
@ -89,8 +89,8 @@ export default class WindowsManager {
} }
/** /**
* @param {String} appId * @param {string} appId
* @returns {Boolean} * @returns {boolean}
*/ */
isAppActive(appId) { isAppActive(appId) {
let active = false; let active = false;

View file

@ -6,7 +6,9 @@ const SettingsContext = createContext();
/** /**
* Note: needs to be inside a virtual root provider * Note: needs to be inside a virtual root provider
* @returns {React.Provider<SettingsManager>} * @param props
* @param props.children
* @returns {import("react").Provider<SettingsManager>}
*/ */
export function SettingsProvider({ children }) { export function SettingsProvider({ children }) {
const virtualRoot = useVirtualRoot(); const virtualRoot = useVirtualRoot();

View file

@ -1,7 +1,7 @@
import { useEffect } from "react"; import { useEffect } from "react";
/** /**
* @param {Object} params * @param {object} params
* @param {Function} params.onKeyDown * @param {Function} params.onKeyDown
* @param {Function} params.onKeyUp * @param {Function} params.onKeyUp
*/ */

View file

@ -2,15 +2,18 @@
* https://stackoverflow.com/a/42234988 * https://stackoverflow.com/a/42234988
*/ */
import React, { useRef, useEffect } from "react"; import { useRef, useEffect } from "react";
/** /**
* Hook that alerts clicks outside of the passed ref * Hook that alerts clicks outside of the passed ref
* @param {import("react").ElementRef} ref
* @param {Function} callback
*/ */
function useOutsideClickListener(ref, callback) { function useOutsideClickListener(ref, callback) {
useEffect(() => { useEffect(() => {
/** /**
* Alert if clicked on outside of element * Alert if clicked on outside of element
* @param event
*/ */
function handleClickOutside(event) { function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) { if (ref.current && !ref.current.contains(event.target)) {
@ -27,8 +30,9 @@ function useOutsideClickListener(ref, callback) {
} }
/** /**
* @param {Object} props * @param {object} props
* @param {Function} props.onOutsideClick * @param {Function} props.onOutsideClick
* @param {import("react").ElementType} props.children
*/ */
export default function OutsideClickListener({ onOutsideClick, children }) { export default function OutsideClickListener({ onOutsideClick, children }) {
const wrapperRef = useRef(null); const wrapperRef = useRef(null);

View file

@ -7,16 +7,16 @@ import React, { useCallback, useEffect, useRef } from "react";
import { useState } from "react"; import { useState } from "react";
/** /**
* @param {Object} options * @param {object} options
* @param {React.ElementRef} options.ref * @param {React.ElementRef} options.ref
* @param {Boolean=true} options.horizontal * @param {Boolean=true} options.horizontal
* @param {Boolean=true} options.dynamicOffset * @param {Boolean=true} options.dynamicOffset
* @param {Number=1} options.dynamicOffsetFactor * @param {Number=1} options.dynamicOffsetFactor
* @param {Object} options.shadow * @param {object} options.shadow
* @param {Number=8} options.shadow.offset * @param {Number=8} options.shadow.offset
* @param {Number=5} options.shadow.blurRadius * @param {Number=5} options.shadow.blurRadius
* @param {Number=-5} options.shadow.spreadRadius * @param {Number=-5} options.shadow.spreadRadius
* @param {Object} options.shadow.color * @param {object} options.shadow.color
* @param {Number=0} options.shadow.color.r * @param {Number=0} options.shadow.color.r
* @param {Number=0} options.shadow.color.g * @param {Number=0} options.shadow.color.g
* @param {Number=0} options.shadow.color.b * @param {Number=0} options.shadow.color.b

View file

@ -4,7 +4,9 @@ import { VirtualRoot } from "../../features/virtual-drive/virtual-root.js";
const VirtualRootContext = createContext(); const VirtualRootContext = createContext();
/** /**
* @returns {React.Provider<VirtualRoot>} * @param props
* @param props.children
* @returns {import("react").Provider<VirtualRoot>}
*/ */
export function VirtualRootProvider({ children }) { export function VirtualRootProvider({ children }) {
const virtualRoot = new VirtualRoot().init(); const virtualRoot = new VirtualRoot().init();

View file

@ -3,7 +3,10 @@ import { createContext, useCallback, useContext, useState } from "react";
const WindowsContext = createContext(); const WindowsContext = createContext();
/** /**
* @returns {React.Provider<any>} * @param props
* @param props.children
* @param props.windowsManager
* @returns {import("react").Provider<any>}
*/ */
export function WindowsProvider({ children, windowsManager }) { export function WindowsProvider({ children, windowsManager }) {
const [windows, setWindows] = useState([]); const [windows, setWindows] = useState([]);
@ -22,6 +25,9 @@ export function WindowsProvider({ children, windowsManager }) {
); );
} }
/**
* @returns {object[]}
*/
export function useWindows() { export function useWindows() {
return useContext(WindowsContext); return useContext(WindowsContext);
} }

View file

@ -5,7 +5,9 @@ import { WindowsProvider } from "./WindowsContext.js";
const WindowsManagerContext = createContext(); const WindowsManagerContext = createContext();
/** /**
* @returns {React.Provider<any>} * @param {object} props
* @param {import("react").ElementType} props.children
* @returns {import("react").Provider<any>}
*/ */
export function WindowsManagerProvider({ children }) { export function WindowsManagerProvider({ children }) {
const windowsManager = new WindowsManager(); const windowsManager = new WindowsManager();