Added app error handling + made modals global
This commit is contained in:
parent
bca11ddfd2
commit
0bd7e8502b
21 changed files with 192 additions and 130 deletions
37
package-lock.json
generated
37
package-lock.json
generated
|
|
@ -22,6 +22,7 @@
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-draggable": "^4.4.5",
|
"react-draggable": "^4.4.5",
|
||||||
|
"react-error-boundary": "^4.0.13",
|
||||||
"react-ga4": "^2.1.0",
|
"react-ga4": "^2.1.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-svg": "^16.1.18",
|
"react-svg": "^16.1.18",
|
||||||
|
|
@ -31,7 +32,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"babel-plugin-wildcard": "^7.0.0",
|
|
||||||
"eslint-plugin-jsdoc": "^46.4.6",
|
"eslint-plugin-jsdoc": "^46.4.6",
|
||||||
"gh-pages": "^5.0.0"
|
"gh-pages": "^5.0.0"
|
||||||
}
|
}
|
||||||
|
|
@ -5637,30 +5637,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz",
|
||||||
"integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA=="
|
"integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA=="
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-wildcard": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-wildcard/-/babel-plugin-wildcard-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-3duaRaULzxmmgr+YO9EPEE3m/irVyOWKvXCOz2S41tlp0g2UarSEtpM++D3IS+asK205OOqW1ajnjFeoRRqfZg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"bpwc": "index.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/babel-plugin-wildcard/node_modules/rimraf": {
|
|
||||||
"version": "2.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
|
||||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"glob": "^7.1.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"rimraf": "bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/babel-preset-current-node-syntax": {
|
"node_modules/babel-preset-current-node-syntax": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
|
||||||
|
|
@ -15079,6 +15055,17 @@
|
||||||
"react-dom": ">= 16.3.0"
|
"react-dom": ">= 16.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-error-boundary": {
|
||||||
|
"version": "4.0.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz",
|
||||||
|
"integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-error-overlay": {
|
"node_modules/react-error-overlay": {
|
||||||
"version": "6.0.11",
|
"version": "6.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-draggable": "^4.4.5",
|
"react-draggable": "^4.4.5",
|
||||||
|
"react-error-boundary": "^4.0.13",
|
||||||
"react-ga4": "^2.1.0",
|
"react-ga4": "^2.1.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-svg": "^16.1.18",
|
"react-svg": "^16.1.18",
|
||||||
|
|
|
||||||
19
src/App.jsx
19
src/App.jsx
|
|
@ -9,6 +9,7 @@ import { ModalsView } from "./components/modals/ModalsView.jsx";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { ZIndexManagerProvider } from "./hooks/z-index/zIndexManagerContext.js";
|
import { ZIndexManagerProvider } from "./hooks/z-index/zIndexManagerContext.js";
|
||||||
import { TrackingManager } from "./features/tracking/trackingManager.js";
|
import { TrackingManager } from "./features/tracking/trackingManager.js";
|
||||||
|
import { ModalsManagerProvider } from "./hooks/modals/modalsManagerContext.js";
|
||||||
|
|
||||||
TrackingManager.initialize();
|
TrackingManager.initialize();
|
||||||
|
|
||||||
|
|
@ -29,14 +30,16 @@ function App() {
|
||||||
<VirtualRootProvider>
|
<VirtualRootProvider>
|
||||||
<ZIndexManagerProvider>
|
<ZIndexManagerProvider>
|
||||||
<WindowsManagerProvider>
|
<WindowsManagerProvider>
|
||||||
<SettingsManagerProvider>
|
<ModalsManagerProvider>
|
||||||
<div className={styles.App}>
|
<SettingsManagerProvider>
|
||||||
<Taskbar/>
|
<div className={styles.App}>
|
||||||
<WindowsView/>
|
<Taskbar/>
|
||||||
<ModalsView/>
|
<WindowsView/>
|
||||||
<Desktop/>
|
<ModalsView/>
|
||||||
</div>
|
<Desktop/>
|
||||||
</SettingsManagerProvider>
|
</div>
|
||||||
|
</SettingsManagerProvider>
|
||||||
|
</ModalsManagerProvider>
|
||||||
</WindowsManagerProvider>
|
</WindowsManagerProvider>
|
||||||
</ZIndexManagerProvider>
|
</ZIndexManagerProvider>
|
||||||
</VirtualRootProvider>
|
</VirtualRootProvider>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config.js";
|
||||||
* @param {import("./directory-list/DirectoryList.jsx").onSelectionChange} props.onSelectionChange
|
* @param {import("./directory-list/DirectoryList.jsx").onSelectionChange} props.onSelectionChange
|
||||||
* @param {Function} props.onSelectionFinish
|
* @param {Function} props.onSelectionFinish
|
||||||
*/
|
*/
|
||||||
export function FileExplorer({ startPath, selectorMode, Footer, modalsManager, onSelectionChange, onSelectionFinish }) {
|
export function FileExplorer({ startPath, selectorMode, Footer, onSelectionChange, onSelectionFinish }) {
|
||||||
const isSelector = (Footer != null && selectorMode != null && selectorMode !== SELECTOR_MODE.NONE);
|
const isSelector = (Footer != null && selectorMode != null && selectorMode !== SELECTOR_MODE.NONE);
|
||||||
|
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
|
|
@ -41,8 +41,8 @@ export function FileExplorer({ startPath, selectorMode, Footer, modalsManager, o
|
||||||
const [showHidden] = useState(true);
|
const [showHidden] = useState(true);
|
||||||
const { history, stateIndex, pushState, undo, redo, undoAvailable, redoAvailable } = useHistory(currentDirectory.path);
|
const { history, stateIndex, pushState, undo, redo, undoAvailable, redoAvailable } = useHistory(currentDirectory.path);
|
||||||
|
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
const { openWindowedModal } = useWindowedModal();
|
||||||
const { onContextMenu: onContextMenuFile } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu: onContextMenuFile } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label={!isSelector ? "Open" : "Select"} onTrigger={(event, file) => {
|
<ClickAction label={!isSelector ? "Open" : "Select"} onTrigger={(event, file) => {
|
||||||
if (isSelector) {
|
if (isSelector) {
|
||||||
|
|
@ -65,7 +65,7 @@ export function FileExplorer({ startPath, selectorMode, Footer, modalsManager, o
|
||||||
}}/>
|
}}/>
|
||||||
</Actions>
|
</Actions>
|
||||||
});
|
});
|
||||||
const { onContextMenu: onContextMenuFolder } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu: onContextMenuFolder } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label="Open" onTrigger={(event, folder) => {
|
<ClickAction label="Open" onTrigger={(event, folder) => {
|
||||||
changeDirectory(folder.linkedPath ?? folder.name);
|
changeDirectory(folder.linkedPath ?? folder.name);
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ import { removeFromArray } from "../../../../features/_utils/array.utils.js";
|
||||||
import { useSettingsManager } from "../../../../hooks/settings/settingsManagerContext.js";
|
import { useSettingsManager } from "../../../../hooks/settings/settingsManagerContext.js";
|
||||||
import { SettingsManager } from "../../../../features/settings/settingsManager.js";
|
import { SettingsManager } from "../../../../features/settings/settingsManager.js";
|
||||||
|
|
||||||
export function AppOption({ app, pins, setPins, modalsManager }) {
|
export function AppOption({ app, pins, setPins }) {
|
||||||
const isPinned = pins.includes(app.id);
|
const isPinned = pins.includes(app.id);
|
||||||
|
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
|
|
||||||
const { onContextMenu } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label="Launch" icon={AppsManager.getAppIconUrl(app.id)} onTrigger={() => windowsManager.open(app.id)}/>
|
<ClickAction label="Launch" icon={AppsManager.getAppIconUrl(app.id)} onTrigger={() => windowsManager.open(app.id)}/>
|
||||||
<ClickAction label={isPinned ? "Unpin from taskbar" : "Pin to taskbar"} icon={faThumbTack} onTrigger={() => {
|
<ClickAction label={isPinned ? "Unpin from taskbar" : "Pin to taskbar"} icon={faThumbTack} onTrigger={() => {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export function AppearanceSettings({ modalsManager }) {
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
const [wallpaper, setWallpaper] = useState(null);
|
const [wallpaper, setWallpaper] = useState(null);
|
||||||
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
|
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
const { openWindowedModal } = useWindowedModal();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
settings.get("wallpaper", setWallpaper);
|
settings.get("wallpaper", setWallpaper);
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export function TextEditor({ file, setTitle, setIconUrl, close, mode, app, modal
|
||||||
const [content, setContent] = useState(file?.content ?? "");
|
const [content, setContent] = useState(file?.content ?? "");
|
||||||
const [unsavedChanges, setUnsavedChanges] = useState(file == null);
|
const [unsavedChanges, setUnsavedChanges] = useState(file == null);
|
||||||
const [zoom, setZoom] = useState(DEFAULT_ZOOM);
|
const [zoom, setZoom] = useState(DEFAULT_ZOOM);
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
const { openWindowedModal } = useWindowedModal();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { useContextMenu } from "../../../../hooks/modals/contextMenu.js";
|
import { useContextMenu } from "../../../../hooks/modals/contextMenu.js";
|
||||||
import { Actions } from "../../../actions/Actions.jsx";
|
import { Actions } from "../../../actions/Actions.jsx";
|
||||||
import { ClickAction } from "../../../actions/actions/ClickAction.jsx";
|
import { ClickAction } from "../../../actions/actions/ClickAction.jsx";
|
||||||
import ModalsManager from "../../../../features/modals/modalsManager.js";
|
|
||||||
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile.js";
|
import { VirtualFile } from "../../../../features/virtual-drive/file/virtualFile.js";
|
||||||
import { useWindowedModal } from "../../../../hooks/modals/windowedModal.js";
|
import { useWindowedModal } from "../../../../hooks/modals/windowedModal.js";
|
||||||
import AppsManager from "../../../../features/apps/appsManager.js";
|
import AppsManager from "../../../../features/apps/appsManager.js";
|
||||||
|
|
@ -18,14 +17,13 @@ import { APPS } from "../../../../config/apps.config.js";
|
||||||
* @param {object} props
|
* @param {object} props
|
||||||
* @param {string} props.href
|
* @param {string} props.href
|
||||||
* @param {*} props.children
|
* @param {*} props.children
|
||||||
* @param {ModalsManager} props.modalsManager
|
|
||||||
* @param {WindowsManager} props.windowsManager
|
* @param {WindowsManager} props.windowsManager
|
||||||
* @param {Function} props.setCurrentFile
|
* @param {Function} props.setCurrentFile
|
||||||
* @param {VirtualFile} props.currentFile
|
* @param {VirtualFile} props.currentFile
|
||||||
* @param {App} props.app
|
* @param {App} props.app
|
||||||
*/
|
*/
|
||||||
export function MarkdownLink({ href, children, modalsManager, windowsManager, currentFile, setCurrentFile, app, ...props }) {
|
export function MarkdownLink({ href, children, windowsManager, currentFile, setCurrentFile, app, ...props }) {
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
const { openWindowedModal } = useWindowedModal();
|
||||||
|
|
||||||
const onClick = (event) => {
|
const onClick = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -55,7 +53,7 @@ export function MarkdownLink({ href, children, modalsManager, windowsManager, cu
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { onContextMenu } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label="Open link" icon={faExternalLink} onTrigger={onClick}/>
|
<ClickAction label="Open link" icon={faExternalLink} onTrigger={onClick}/>
|
||||||
</Actions>
|
</Actions>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ import { SettingsManager } from "../../features/settings/settingsManager.js";
|
||||||
import { useSettingsManager } from "../../hooks/settings/settingsManagerContext.js";
|
import { useSettingsManager } from "../../hooks/settings/settingsManagerContext.js";
|
||||||
import styles from "./Desktop.module.css";
|
import styles from "./Desktop.module.css";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useModals } from "../../hooks/modals/modals.js";
|
|
||||||
import { ModalsView } from "../modals/ModalsView.jsx";
|
|
||||||
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
||||||
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
||||||
import { FALLBACK_ICON_SIZE, FALLBACK_WALLPAPER } from "../../config/desktop.config.js";
|
import { FALLBACK_ICON_SIZE, FALLBACK_WALLPAPER } from "../../config/desktop.config.js";
|
||||||
|
|
@ -24,11 +22,12 @@ import { isValidInteger } from "../../features/_utils/number.utils.js";
|
||||||
import { useWindowedModal } from "../../hooks/modals/windowedModal.js";
|
import { useWindowedModal } from "../../hooks/modals/windowedModal.js";
|
||||||
import { Share } from "../modals/share/Share.jsx";
|
import { Share } from "../modals/share/Share.jsx";
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
import ModalsManager from "../../features/modals/modalsManager.js";
|
||||||
|
import { useModalsManager } from "../../hooks/modals/modalsManagerContext.js";
|
||||||
|
|
||||||
export const Desktop = memo(() => {
|
export const Desktop = memo(() => {
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
const [wallpaper, setWallpaper] = useState(null);
|
const [wallpaper, setWallpaper] = useState(null);
|
||||||
const [modalsManager, modals] = useModals();
|
const modalsManager = useModalsManager();
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
const [showIcons, setShowIcons] = useState(false);
|
const [showIcons, setShowIcons] = useState(false);
|
||||||
|
|
@ -138,7 +137,6 @@ export const Desktop = memo(() => {
|
||||||
className={styles.Container}
|
className={styles.Container}
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
<ModalsView modalsManager={modalsManager} modals={modals}/>
|
|
||||||
{showIcons && <DirectoryList
|
{showIcons && <DirectoryList
|
||||||
directory={directory}
|
directory={directory}
|
||||||
className={styles.Content}
|
className={styles.Content}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,30 @@
|
||||||
import { memo, useEffect, useRef } from "react";
|
import { memo, useEffect, useRef, useState } from "react";
|
||||||
import { Modal } from "../../features/modals/modal.js";
|
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
|
||||||
import { ModalView } from "./ModalView.jsx";
|
import { ModalView } from "./ModalView.jsx";
|
||||||
import styles from "./ModalsView.module.css";
|
import styles from "./ModalsView.module.css";
|
||||||
|
import { useModals } from "../../hooks/modals/modalsContext.js";
|
||||||
|
import { useModalsManager } from "../../hooks/modals/modalsManagerContext.js";
|
||||||
|
|
||||||
/**
|
export const ModalsView = memo(() => {
|
||||||
* @param {object} root
|
|
||||||
* @param {ModalsManager} root.modalsManager
|
|
||||||
* @param {Modal[]} root.modals
|
|
||||||
* @param {import("react").CSSProperties} root.style
|
|
||||||
* @param {import("react").className} root.className
|
|
||||||
*/
|
|
||||||
export const ModalsView = memo(({ modalsManager, modals, style, className, ...props }) => {
|
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
const modals = useModals();
|
||||||
|
const modalsManager = useModalsManager();
|
||||||
|
const [sortedModals, setSortedModals] = useState([]);
|
||||||
|
|
||||||
|
// Sort modals
|
||||||
|
useEffect(() => {
|
||||||
|
setSortedModals([...modals].sort((modalA, modalB) =>
|
||||||
|
modalA.lastInteraction - modalB.lastInteraction
|
||||||
|
));
|
||||||
|
}, [modals]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (modalsManager)
|
if (modalsManager)
|
||||||
modalsManager.containerRef = ref;
|
modalsManager.containerRef = ref;
|
||||||
}, [modalsManager, ref]);
|
}, [modalsManager, ref]);
|
||||||
|
|
||||||
return (
|
return <div ref={ref} className={styles.Container}>
|
||||||
<div ref={ref} style={style} className={`${styles.Container} ${className ?? ""}`} {...props}>
|
{sortedModals?.map((modal) =>
|
||||||
{modals?.map((modal) =>
|
<ModalView key={modal.id} modal={modal}/>
|
||||||
<ModalView key={modal.id} modal={modal}/>
|
)}
|
||||||
)}
|
</div>;
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { APP_ICONS } from "../../../config/apps.config.js";
|
import { APP_ICONS } from "../../../config/apps.config.js";
|
||||||
import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config.js";
|
import { SELECTOR_MODE } from "../../../config/apps/fileExplorer.config.js";
|
||||||
import { useModals } from "../../../hooks/modals/modals.js";
|
|
||||||
import { Button } from "../../_utils/button/Button.jsx";
|
import { Button } from "../../_utils/button/Button.jsx";
|
||||||
import { FileExplorer } from "../../apps/file-explorer/FileExplorer.jsx";
|
import { FileExplorer } from "../../apps/file-explorer/FileExplorer.jsx";
|
||||||
import { ModalsView } from "../ModalsView.jsx";
|
|
||||||
import { WindowedModal } from "../_utils/WindowedModal.jsx";
|
import { WindowedModal } from "../_utils/WindowedModal.jsx";
|
||||||
import styles from "./FileSelector.module.css";
|
import styles from "./FileSelector.module.css";
|
||||||
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile.js";
|
import { VirtualFile } from "../../../features/virtual-drive/file/virtualFile.js";
|
||||||
import Modal from "../../../features/modals/modal.js";
|
import Modal from "../../../features/modals/modal.js";
|
||||||
|
import { useModalsManager } from "../../../hooks/modals/modalsManagerContext.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback onFinish
|
* @callback onFinish
|
||||||
|
|
@ -26,7 +25,7 @@ import Modal from "../../../features/modals/modal.js";
|
||||||
export function FileSelector({ modal, params, type, allowedFormats, onFinish, ...props }) {
|
export function FileSelector({ modal, params, type, allowedFormats, onFinish, ...props }) {
|
||||||
const multi = (type === SELECTOR_MODE.MULTIPLE);
|
const multi = (type === SELECTOR_MODE.MULTIPLE);
|
||||||
|
|
||||||
const [modalsManager, modals] = useModals();
|
const modalsManager = useModalsManager();
|
||||||
const [selection, setSelection] = useState(multi ? [] : null);
|
const [selection, setSelection] = useState(multi ? [] : null);
|
||||||
const [directory, setDirectory] = useState(null);
|
const [directory, setDirectory] = useState(null);
|
||||||
|
|
||||||
|
|
@ -58,7 +57,6 @@ export function FileSelector({ modal, params, type, allowedFormats, onFinish, ..
|
||||||
iconUrl: APP_ICONS.FILE_EXPLORER,
|
iconUrl: APP_ICONS.FILE_EXPLORER,
|
||||||
...params,
|
...params,
|
||||||
}} {...props}>
|
}} {...props}>
|
||||||
<ModalsView modalsManager={modalsManager} modals={modals}/>
|
|
||||||
<FileExplorer
|
<FileExplorer
|
||||||
modalsManager={modalsManager}
|
modalsManager={modalsManager}
|
||||||
selectorMode={type}
|
selectorMode={type}
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,16 @@ import { useScrollWithShadow } from "../../hooks/_utils/scrollWithShadows.js";
|
||||||
import { AppButton } from "./app-icon/AppIcon.jsx";
|
import { AppButton } from "./app-icon/AppIcon.jsx";
|
||||||
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
||||||
import { Actions } from "../actions/Actions.jsx";
|
import { Actions } from "../actions/Actions.jsx";
|
||||||
import { useModals } from "../../hooks/modals/modals.js";
|
|
||||||
import { ClickAction } from "../actions/actions/ClickAction.jsx";
|
import { ClickAction } from "../actions/actions/ClickAction.jsx";
|
||||||
import { APPS, APP_NAMES } from "../../config/apps.config.js";
|
import { APPS, APP_NAMES } from "../../config/apps.config.js";
|
||||||
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
||||||
import { ModalsView } from "../modals/ModalsView.jsx";
|
|
||||||
import { TASKBAR_HEIGHT } from "../../config/taskbar.config.js";
|
import { TASKBAR_HEIGHT } from "../../config/taskbar.config.js";
|
||||||
import { useSettingsManager } from "../../hooks/settings/settingsManagerContext.js";
|
import { useSettingsManager } from "../../hooks/settings/settingsManagerContext.js";
|
||||||
import { SettingsManager } from "../../features/settings/settingsManager.js";
|
import { SettingsManager } from "../../features/settings/settingsManager.js";
|
||||||
import { useWindows } from "../../hooks/windows/windowsContext.js";
|
import { useWindows } from "../../hooks/windows/windowsContext.js";
|
||||||
import { ZIndexManager } from "../../features/z-index/zIndexManager.js";
|
import { ZIndexManager } from "../../features/z-index/zIndexManager.js";
|
||||||
import { useZIndex } from "../../hooks/z-index/zIndex.js";
|
import { useZIndex } from "../../hooks/z-index/zIndex.js";
|
||||||
|
import { useModalsManager } from "../../hooks/modals/modalsManagerContext.js";
|
||||||
|
|
||||||
export const Taskbar = memo(() => {
|
export const Taskbar = memo(() => {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
@ -41,7 +40,7 @@ export const Taskbar = memo(() => {
|
||||||
color: { a: 25 }
|
color: { a: 25 }
|
||||||
} });
|
} });
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const [modalsManager, modals] = useModals();
|
const modalsManager = useModalsManager();
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
const windows = useWindows();
|
const windows = useWindows();
|
||||||
const { onContextMenu } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu } = useContextMenu({ modalsManager, Actions: (props) =>
|
||||||
|
|
@ -53,7 +52,6 @@ export const Taskbar = memo(() => {
|
||||||
});
|
});
|
||||||
const [pins, setPins] = useState([]);
|
const [pins, setPins] = useState([]);
|
||||||
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.TASKBAR, index: 0 });
|
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.TASKBAR, index: 0 });
|
||||||
const modalsZIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.TASKBAR, index: 1 });
|
|
||||||
|
|
||||||
const apps = useMemo(() => AppsManager.APPS.sort((appA, appB) => {
|
const apps = useMemo(() => AppsManager.APPS.sort((appA, appB) => {
|
||||||
const indexA = pins.indexOf(appA.id);
|
const indexA = pins.indexOf(appA.id);
|
||||||
|
|
@ -132,7 +130,6 @@ export const Taskbar = memo(() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<ModalsView modalsManager={modalsManager} modals={modals} style={{ zIndex: modalsZIndex }}/>
|
|
||||||
<div
|
<div
|
||||||
style={{ "--taskbar-height": `${TASKBAR_HEIGHT}px`, zIndex }}
|
style={{ "--taskbar-height": `${TASKBAR_HEIGHT}px`, zIndex }}
|
||||||
className={styles["Taskbar"]}
|
className={styles["Taskbar"]}
|
||||||
|
|
|
||||||
28
src/components/windows/WindowFallbackView.jsx
Normal file
28
src/components/windows/WindowFallbackView.jsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useModalsManager } from "../../hooks/modals/modalsManagerContext.js";
|
||||||
|
import { useAlert } from "../../hooks/modals/alert.js";
|
||||||
|
import AppsManager from "../../features/apps/appsManager.js";
|
||||||
|
import Vector2 from "../../features/math/vector2.js";
|
||||||
|
|
||||||
|
export default function WindowFallbackView({ error, resetErrorBoundary, app, closeWindow }) {
|
||||||
|
const modalsManager = useModalsManager();
|
||||||
|
const { alert } = useAlert({ modalsManager });
|
||||||
|
const [alerted, setAlerted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (alerted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setAlerted(true);
|
||||||
|
closeWindow();
|
||||||
|
alert({
|
||||||
|
title: `${app.name} has stopped working`,
|
||||||
|
text: `${error.name}: ${error.message}`,
|
||||||
|
iconUrl: AppsManager.getAppIconUrl(app.id),
|
||||||
|
size: new Vector2(350, 150),
|
||||||
|
single: true
|
||||||
|
});
|
||||||
|
}, [alerted, alert, app.id, app.name, error.message, closeWindow, error.name]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
@ -9,8 +9,6 @@ import App from "../../features/apps/app.js";
|
||||||
import Vector2 from "../../features/math/vector2.js";
|
import Vector2 from "../../features/math/vector2.js";
|
||||||
import { faWindowMaximize } from "@fortawesome/free-regular-svg-icons";
|
import { faWindowMaximize } from "@fortawesome/free-regular-svg-icons";
|
||||||
import utilStyles from "../../styles/utils.module.css";
|
import utilStyles from "../../styles/utils.module.css";
|
||||||
import { useModals } from "../../hooks/modals/modals.js";
|
|
||||||
import { ModalsView } from "../modals/ModalsView.jsx";
|
|
||||||
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
||||||
import AppsManager from "../../features/apps/appsManager.js";
|
import AppsManager from "../../features/apps/appsManager.js";
|
||||||
import { ClickAction } from "../actions/actions/ClickAction.jsx";
|
import { ClickAction } from "../actions/actions/ClickAction.jsx";
|
||||||
|
|
@ -24,6 +22,8 @@ import { useWindowedModal } from "../../hooks/modals/windowedModal.js";
|
||||||
import { Divider } from "../actions/actions/Divider.jsx";
|
import { Divider } from "../actions/actions/Divider.jsx";
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
import ModalsManager from "../../features/modals/modalsManager.js";
|
||||||
import { Share } from "../modals/share/Share.jsx";
|
import { Share } from "../modals/share/Share.jsx";
|
||||||
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
|
import WindowFallbackView from "./WindowFallbackView.jsx";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} windowProps
|
* @typedef {object} windowProps
|
||||||
|
|
@ -52,8 +52,7 @@ import { Share } from "../modals/share/Share.jsx";
|
||||||
export const WindowView = memo(({ id, app, size, position, onInteract, options, active, fullscreen, minimized, toggleMinimized, index }) => {
|
export const WindowView = memo(({ id, app, size, position, onInteract, options, active, fullscreen, minimized, toggleMinimized, index }) => {
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
const nodeRef = useRef(null);
|
const nodeRef = useRef(null);
|
||||||
const [modalsManager, modals] = useModals();
|
const { openWindowedModal } = useWindowedModal();
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
|
||||||
|
|
||||||
const [startSize, setStartSize] = useState(size);
|
const [startSize, setStartSize] = useState(size);
|
||||||
const [startPosition, setStartPosition] = useState(position);
|
const [startPosition, setStartPosition] = useState(position);
|
||||||
|
|
@ -63,7 +62,7 @@ export const WindowView = memo(({ id, app, size, position, onInteract, options,
|
||||||
const [iconUrl, setIconUrl] = useState(AppsManager.getAppIconUrl(app.id));
|
const [iconUrl, setIconUrl] = useState(AppsManager.getAppIconUrl(app.id));
|
||||||
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.WINDOWS, index });
|
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.WINDOWS, index });
|
||||||
|
|
||||||
const { onContextMenu, ShortcutsListener } = useContextMenu({ modalsManager, Actions: (props) =>
|
const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label="Minimize" icon={faMinus} onTrigger={toggleMinimized}/>
|
<ClickAction label="Minimize" icon={faMinus} onTrigger={toggleMinimized}/>
|
||||||
<ClickAction label="Maximize" icon={faExpand} shortcut={["F11"]} onTrigger={() => {
|
<ClickAction label="Maximize" icon={faExpand} shortcut={["F11"]} onTrigger={() => {
|
||||||
|
|
@ -142,7 +141,6 @@ export const WindowView = memo(({ id, app, size, position, onInteract, options,
|
||||||
|
|
||||||
return (<div style={{ zIndex, position: !maximized ? "relative" : null }}>
|
return (<div style={{ zIndex, position: !maximized ? "relative" : null }}>
|
||||||
<ShortcutsListener/>
|
<ShortcutsListener/>
|
||||||
<ModalsView modalsManager={modalsManager} modals={modals} style={{ zIndex: 1 }}/>
|
|
||||||
<Draggable
|
<Draggable
|
||||||
key={id}
|
key={id}
|
||||||
axis="both"
|
axis="both"
|
||||||
|
|
@ -203,16 +201,25 @@ export const WindowView = memo(({ id, app, size, position, onInteract, options,
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["Window-content"]}>
|
<div className={styles["Window-content"]}>
|
||||||
<app.WindowContent
|
<ErrorBoundary
|
||||||
{...options}
|
FallbackComponent={(props) => <WindowFallbackView app={app} closeWindow={close} {...props}/>}
|
||||||
app={app}
|
onReset={(details) => {
|
||||||
setTitle={setTitle}
|
// Reset the state of your app so the error doesn't happen again
|
||||||
setIconUrl={setIconUrl}
|
}}
|
||||||
close={close}
|
onError={(error) => {
|
||||||
focus={focus}
|
console.error(error);
|
||||||
active={active}
|
}}
|
||||||
modalsManager={modalsManager}
|
>
|
||||||
/>
|
<app.WindowContent
|
||||||
|
{...options}
|
||||||
|
app={app}
|
||||||
|
setTitle={setTitle}
|
||||||
|
setIconUrl={setIconUrl}
|
||||||
|
close={close}
|
||||||
|
focus={focus}
|
||||||
|
active={active}
|
||||||
|
/>
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ export default class ModalsManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Modal} modal
|
* @param {Modal} modal
|
||||||
* @param {boolean} closeOthers - Set to false to preserve other open modals
|
* @param {boolean} single - Set to false to preserve other open modals
|
||||||
*/
|
*/
|
||||||
open(modal, closeOthers = true) {
|
open(modal, single = true) {
|
||||||
if (closeOthers) {
|
if (single) {
|
||||||
this.modalIds.forEach((id) => {
|
this.modalIds.forEach((id) => {
|
||||||
this.close(id, false);
|
this.close(id, false);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { DialogBox } from "../../components/modals/dialog-box/DialogBox.jsx";
|
||||||
import { DIALOG_CONTENT_TYPES } from "../../config/modals.config.js";
|
import { DIALOG_CONTENT_TYPES } from "../../config/modals.config.js";
|
||||||
import Vector2 from "../../features/math/vector2.js";
|
import Vector2 from "../../features/math/vector2.js";
|
||||||
import { useWindowedModal } from "./windowedModal.js";
|
import { useWindowedModal } from "./windowedModal.js";
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef alertType
|
* @typedef alertType
|
||||||
|
|
@ -14,18 +13,17 @@ import ModalsManager from "../../features/modals/modalsManager.js";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} props
|
|
||||||
* @param {ModalsManager} props.modalsManager
|
|
||||||
* @returns {{ alert: alertType }}
|
* @returns {{ alert: alertType }}
|
||||||
*/
|
*/
|
||||||
export function useAlert({ modalsManager }) {
|
export function useAlert() {
|
||||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
const { openWindowedModal } = useWindowedModal();
|
||||||
|
|
||||||
const alert = useCallback(({ title, text, iconUrl }) => {
|
const alert = useCallback(({ title, text, iconUrl, size, single }) => {
|
||||||
openWindowedModal({
|
openWindowedModal({
|
||||||
title: title ?? "Alert",
|
title: title ?? "Alert",
|
||||||
iconUrl,
|
iconUrl,
|
||||||
size: new Vector2(300, 150),
|
size: size ?? new Vector2(300, 150),
|
||||||
|
single,
|
||||||
Modal: (props) =>
|
Modal: (props) =>
|
||||||
<DialogBox {...props}>
|
<DialogBox {...props}>
|
||||||
<p>{text}</p>
|
<p>{text}</p>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import Vector2 from "../../features/math/vector2.js";
|
import Vector2 from "../../features/math/vector2.js";
|
||||||
import Modal from "../../features/modals/modal.js";
|
import Modal from "../../features/modals/modal.js";
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
|
||||||
import { STYLES } from "../../components/actions/Actions.jsx";
|
import { STYLES } from "../../components/actions/Actions.jsx";
|
||||||
|
import { useModalsManager } from "./modalsManagerContext.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback onContextMenuType
|
* @callback onContextMenuType
|
||||||
|
|
@ -13,14 +13,15 @@ import { STYLES } from "../../components/actions/Actions.jsx";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} props
|
* @param {object} props
|
||||||
* @param {ModalsManager} props.modalsManager
|
|
||||||
* @param {import("../../components/actions/Actions.jsx").actionsType} props.Actions
|
* @param {import("../../components/actions/Actions.jsx").actionsType} props.Actions
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* onContextMenu: onContextMenuType,
|
* onContextMenu: onContextMenuType,
|
||||||
* ShortcutsListener: import("../../components/actions/Actions.jsx").actionsType
|
* ShortcutsListener: import("../../components/actions/Actions.jsx").actionsType
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function useContextMenu({ modalsManager, Actions }) {
|
export function useContextMenu({ Actions }) {
|
||||||
|
const modalsManager = useModalsManager();
|
||||||
|
|
||||||
// Open a new modal when context menu is triggered
|
// Open a new modal when context menu is triggered
|
||||||
const onContextMenu = useCallback((event, params = {}) => {
|
const onContextMenu = useCallback((event, params = {}) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import { useCallback, useState } from "react";
|
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
|
||||||
import Modal from "../../features/modals/modal.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {[ModalsManager, Modal[]]}
|
|
||||||
*/
|
|
||||||
export function useModals() {
|
|
||||||
const modalsManager = new ModalsManager();
|
|
||||||
const [modals, setModals] = useState([]);
|
|
||||||
|
|
||||||
const updateModals = useCallback((updatedModals) => {
|
|
||||||
setModals(Object.values(updatedModals));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
modalsManager.setUpdateModals(updateModals);
|
|
||||||
|
|
||||||
return [modalsManager, modals];
|
|
||||||
}
|
|
||||||
33
src/hooks/modals/modalsContext.js
Normal file
33
src/hooks/modals/modalsContext.js
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { createContext, useCallback, useContext, useState } from "react";
|
||||||
|
import Modal from "../../features/modals/modal.js";
|
||||||
|
|
||||||
|
const ModalsContext = createContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param props
|
||||||
|
* @param props.children
|
||||||
|
* @param props.modalsManager
|
||||||
|
* @returns {import("react").Provider<any>}
|
||||||
|
*/
|
||||||
|
export function ModalsProvider({ children, modalsManager }) {
|
||||||
|
const [modals, setModals] = useState([]);
|
||||||
|
|
||||||
|
const updateModals = useCallback((updatedModals) => {
|
||||||
|
setModals(Object.values(updatedModals));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
modalsManager.setUpdateModals(updateModals);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalsContext.Provider value={modals}>
|
||||||
|
{children}
|
||||||
|
</ModalsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Modal[]}
|
||||||
|
*/
|
||||||
|
export function useModals() {
|
||||||
|
return useContext(ModalsContext);
|
||||||
|
}
|
||||||
29
src/hooks/modals/modalsManagerContext.js
Normal file
29
src/hooks/modals/modalsManagerContext.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { createContext, useContext } from "react";
|
||||||
|
import ModalsManager from "../../features/modals/modalsManager.js";
|
||||||
|
import { ModalsProvider } from "./modalsContext.js";
|
||||||
|
|
||||||
|
const modalsManagerContext = createContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} props
|
||||||
|
* @param {import("react").ElementType} props.children
|
||||||
|
* @returns {import("react").Provider<any>}
|
||||||
|
*/
|
||||||
|
export function ModalsManagerProvider({ children }) {
|
||||||
|
const modalsManager = new ModalsManager();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<modalsManagerContext.Provider value={modalsManager}>
|
||||||
|
<ModalsProvider modalsManager={modalsManager}>
|
||||||
|
{children}
|
||||||
|
</ModalsProvider>
|
||||||
|
</modalsManagerContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {ModalsManager}
|
||||||
|
*/
|
||||||
|
export function useModalsManager() {
|
||||||
|
return useContext(modalsManagerContext);
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import { useCallback } from "react";
|
||||||
import Modal from "../../features/modals/modal.js";
|
import Modal from "../../features/modals/modal.js";
|
||||||
import Vector2 from "../../features/math/vector2.js";
|
import Vector2 from "../../features/math/vector2.js";
|
||||||
import { DEFAULT_DIALOG_SIZE } from "../../config/modals.config.js";
|
import { DEFAULT_DIALOG_SIZE } from "../../config/modals.config.js";
|
||||||
import ModalsManager from "../../features/modals/modalsManager.js";
|
import { useModalsManager } from "./modalsManagerContext.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback windowedModalType
|
* @callback windowedModalType
|
||||||
|
|
@ -20,11 +20,11 @@ import ModalsManager from "../../features/modals/modalsManager.js";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} props
|
|
||||||
* @param {ModalsManager} props.modalsManager
|
|
||||||
* @returns {{ openWindowedModal: openWindowedModalType }}
|
* @returns {{ openWindowedModal: openWindowedModalType }}
|
||||||
*/
|
*/
|
||||||
export function useWindowedModal({ modalsManager }) {
|
export function useWindowedModal() {
|
||||||
|
const modalsManager = useModalsManager();
|
||||||
|
|
||||||
const openWindowedModal = useCallback(({ Modal: WindowedModal, ...params }) => {
|
const openWindowedModal = useCallback(({ Modal: WindowedModal, ...params }) => {
|
||||||
const size = params.size ?? DEFAULT_DIALOG_SIZE;
|
const size = params.size ?? DEFAULT_DIALOG_SIZE;
|
||||||
let positionX = (window.innerWidth - size.x) / 4;
|
let positionX = (window.innerWidth - size.x) / 4;
|
||||||
|
|
@ -42,7 +42,9 @@ export function useWindowedModal({ modalsManager }) {
|
||||||
.setDismissible(false)
|
.setDismissible(false)
|
||||||
.setProps({ params });
|
.setProps({ params });
|
||||||
|
|
||||||
modalsManager.open(newModal, false);
|
const single = params.single ?? false;
|
||||||
|
|
||||||
|
modalsManager.open(newModal, single);
|
||||||
return newModal;
|
return newModal;
|
||||||
}, [modalsManager]);
|
}, [modalsManager]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue