diff --git a/src/components/applications/.common/HeaderMenu.jsx b/src/components/applications/.common/HeaderMenu.jsx index 627f338..eb800b7 100644 --- a/src/components/applications/.common/HeaderMenu.jsx +++ b/src/components/applications/.common/HeaderMenu.jsx @@ -1,56 +1,14 @@ -import { useState } from "react"; -import { removeFromArray } from "../../../features/utils/array.js"; -import { useKeyboardListener } from "../../../hooks/utils/keyboard.js"; +import { useShortcuts } from "../../../hooks/utils/keyboard.js"; import { DropdownButton } from "../../utils/DropdownButton.jsx"; import styles from "./HeaderMenu.module.css"; /** * @param {Object} props - * @param {Object>} props.options - * @param {Object>} props.shortcuts + * @param {Object>} props.options + * @param {Object>} props.shortcuts */ export function HeaderMenu({ options, shortcuts }) { - const [activeKeys, setActiveKeys] = useState([]); - - const checkShortcuts = (event, allowExecution = true) => { - for (const [category, group] of Object.entries(shortcuts)) { - for (const [name, shortcut] of Object.entries(group)) { - let active = true; - - shortcut.forEach((key) => { - if (!activeKeys.includes(key) && event.key != key) - return active = false; - }); - - if (active) { - event.preventDefault(); - if (shortcut.includes(event.key) && allowExecution) { - options?.[category]?.[name]?.(); - } - } - } - } - } - - const onKeyDown = (event) => { - const isRepeated = activeKeys.includes(event.key); - checkShortcuts(event, isRepeated); - - if (!isRepeated) - setActiveKeys(activeKeys.concat([event.key])); - }; - - const onKeyUp = (event) => { - checkShortcuts(event); - - if (activeKeys.includes(event.key)) { - const keys = [...activeKeys]; - removeFromArray(event.key, keys); - setActiveKeys(keys); - } - }; - - useKeyboardListener({ onKeyDown, onKeyUp }); + useShortcuts({ options, shortcuts }); return (
diff --git a/src/components/applications/text-editor/TextEditor.jsx b/src/components/applications/text-editor/TextEditor.jsx index c084648..a17d4e8 100644 --- a/src/components/applications/text-editor/TextEditor.jsx +++ b/src/components/applications/text-editor/TextEditor.jsx @@ -93,7 +93,7 @@ export function TextEditor({ file, setTitle, close, mode, app }) { "New": newText, "Save": saveText, // "Save As": saveTextAs, - "Exit": () => { + "Quit": () => { close(); }, }, @@ -116,7 +116,7 @@ export function TextEditor({ file, setTitle, close, mode, app }) { "File": { "New": ["Control", "e"], "Save": ["Control", "s"], - "Exit": ["Control", "x"], + "Quit": ["Control", "q"], }, "View": { "Zoom In": ["Control", "+"], diff --git a/src/components/desktop/Desktop.jsx b/src/components/desktop/Desktop.jsx index 9901108..f6ce0e5 100644 --- a/src/components/desktop/Desktop.jsx +++ b/src/components/desktop/Desktop.jsx @@ -3,18 +3,23 @@ import { SettingsManager } from "../../features/settings/settings.js"; import { useSettings } from "../../hooks/settings/SettingsContext.js"; import styles from "./Desktop.module.css"; import { useEffect } from "react"; -import { useModals } from "../../hooks/modals/ModalsContext.js"; +import { useModals } from "../../hooks/modals/Modals.js"; import { ModalsView } from "../modals/ModalsView.jsx"; -import Vector2 from "../../features/math/vector2.js"; -import { ContextMenu } from "../modals/context-menu/ContextMenu.jsx"; -import Modal from "../../features/modals/modal.js"; import { useWindowsManager } from "../../hooks/windows/WindowsManagerContext.js"; +import { useContextMenu } from "../../hooks/modals/ContextMenu.js"; export function Desktop() { const settingsManager = useSettings(); const [wallpaper, setWallpaper] = useState(null); const [modalsManager, modals] = useModals(); const windowsManager = useWindowsManager(); + const { onContextMenu } = useContextMenu({ + modalsManager, + options: { + "Change appearance": () => { windowsManager.open("settings", { initialTabIndex: 0 }); }, + "Open in Files": () => { windowsManager.open("file-explorer", { startPath: "~/Desktop" }); } + } + }); useEffect(() => { (async () => { @@ -23,18 +28,6 @@ export function Desktop() { })(); }, [settingsManager]); - const onContextMenu = (event) => { - event.preventDefault(); - modalsManager.open(new Modal(ContextMenu) - .setPosition(new Vector2(event.clientX, event.clientY)) - .setProps({ - options: { - "Change appearance": () => { windowsManager.open("settings", { initialTabIndex: 0 }); }, - "Open in Files": () => { windowsManager.open("file-explorer", { startPath: "~/Desktop" }); } - } - })); - }; - return (<>
diff --git a/src/components/modals/ModalsView.jsx b/src/components/modals/ModalsView.jsx index 3b29b11..5285dc9 100644 --- a/src/components/modals/ModalsView.jsx +++ b/src/components/modals/ModalsView.jsx @@ -1,15 +1,18 @@ import { Modal } from "../../features/modals/modal.js"; import ModalsManager from "../../features/modals/modals.js"; import { ModalView } from "./ModalView.jsx"; +import styles from "./ModalsView.module.css"; /** * @param {object} root * @param {ModalsManager} root.modalsManager * @param {Modal[]} root.modals + * @param {import("react").CSSProperties} root.style + * @param {import("react").className} root.className */ -export function ModalsView({ modalsManager, modals }) { +export function ModalsView({ modalsManager, modals, style, className }) { return ( -
+
{modals?.map((modal) => )} diff --git a/src/components/modals/ModalsView.module.css b/src/components/modals/ModalsView.module.css new file mode 100644 index 0000000..0197d6b --- /dev/null +++ b/src/components/modals/ModalsView.module.css @@ -0,0 +1,3 @@ +.Container { + position: relative; +} \ No newline at end of file diff --git a/src/components/modals/context-menu/ContextMenu.jsx b/src/components/modals/context-menu/ContextMenu.jsx index bf001d8..35e6b3e 100644 --- a/src/components/modals/context-menu/ContextMenu.jsx +++ b/src/components/modals/context-menu/ContextMenu.jsx @@ -11,7 +11,7 @@ import styles from "./ContextMenu.module.css"; export function ContextMenu({ modal, options, shortcuts }) { return (
{Object.entries(options).map(([label, callback]) => -