Fixed bugs related to modals
This commit is contained in:
parent
75666e7135
commit
d73db00326
20 changed files with 105 additions and 45 deletions
|
|
@ -5,34 +5,34 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||
import { faArrowUp, faCaretLeft, faCaretRight, faCog, faDesktop, faFileLines, faHouse, faImage, faPlus, faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useWindowsManager } from "../../../hooks/windows/windowsManagerContext.js";
|
||||
import { useContextMenu } from "../../../hooks/modals/contextMenu.js";
|
||||
import { useModals } from "../../../hooks/modals/modals.js";
|
||||
import { ModalsView } from "../../modals/ModalsView.jsx";
|
||||
import { QuickAccessButton } from "./QuickAccessButton.jsx";
|
||||
import { useDialogBox } from "../../../hooks/modals/dialogBox.js";
|
||||
import Vector2 from "../../../features/math/vector2.js";
|
||||
import { DIALOG_CONTENT_TYPES } from "../../../constants/modals.js";
|
||||
import { DirectoryList } from "./directory-list/DirectoryList.jsx";
|
||||
|
||||
export function FileExplorer({ startPath, app }) {
|
||||
/**
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
*/
|
||||
export function FileExplorer({ startPath, app, modalsManager }) {
|
||||
const virtualRoot = useVirtualRoot();
|
||||
const [currentDirectory, setCurrentDirectory] = useState(virtualRoot.navigate(startPath ?? "~"));
|
||||
const [path, setPath] = useState(currentDirectory?.path ?? "");
|
||||
const windowsManager = useWindowsManager();
|
||||
const [showHidden] = useState(true);
|
||||
const [modalsManager, modals] = useModals();
|
||||
|
||||
const { onContextMenu: onContextMenuFile } = useContextMenu({
|
||||
modalsManager,
|
||||
options: {
|
||||
"Open": ({ file }) => { windowsManager.openFile(file); },
|
||||
"Delete": ({ file }) => { file.delete(); },
|
||||
"Open": (file) => { file.open(windowsManager); },
|
||||
"Delete": (file) => { file.delete(); },
|
||||
}
|
||||
});
|
||||
const { onContextMenu: onContextMenuFolder } = useContextMenu({
|
||||
modalsManager,
|
||||
options: {
|
||||
"Open": ({ name }) => { changeDirectory(name); },
|
||||
"Delete": ({ name }) => { currentDirectory.findSubFolder(name)?.delete(); }
|
||||
"Open": (folder) => { changeDirectory(folder.name); },
|
||||
"Delete": (folder) => { folder.delete(); }
|
||||
}
|
||||
});
|
||||
// const { onContextMenu: onNew } = useContextMenu({
|
||||
|
|
@ -78,7 +78,6 @@ export function FileExplorer({ startPath, app }) {
|
|||
|
||||
return (
|
||||
<div className={styles.Container}>
|
||||
<ModalsView modalsManager={modalsManager} modals={modals}/>
|
||||
<div className={styles.Header}>
|
||||
<button title="Back" tabIndex={0} className={styles["Icon-button"]}>
|
||||
<FontAwesomeIcon icon={faCaretLeft}/>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
|
||||
import { useEffect } from "react";
|
||||
import { VirtualFile } from "../../../features/virtual-drive/virtualFile.js";
|
||||
import { useWindowsManager } from "../../../hooks/windows/windowsManagerContext.js";
|
||||
import styles from "./MediaViewer.module.css";
|
||||
import { APPS } from "../../../constants/applications.js";
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {VirtualFile} props.file
|
||||
* @param {Function} props.close
|
||||
* @param {Function} props.setTitle
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
*/
|
||||
export function MediaViewer({ file, close, setTitle }) {
|
||||
const windowsManager = useWindowsManager();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ import { AboutSettings } from "./AboutSettings.jsx";
|
|||
import { StorageTab } from "./StorageSettings.jsx";
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {number} props.initialTabIndex
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
*/
|
||||
export function Settings({ initialTabIndex }) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import { HOSTNAME, USERNAME } from "../../../constants/applications/terminal.js"
|
|||
import CommandsManager from "../../../features/applications/terminal/commands.js";
|
||||
import { removeFromArray } from "../../../features/utils/array.js";
|
||||
|
||||
/**
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
*/
|
||||
export function Terminal({ setTitle, close: exit }) {
|
||||
const [inputKey, setInputKey] = useState(0);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
|
|
|
|||
|
|
@ -1,20 +1,12 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { VirtualFile } from "../../../features/virtual-drive/virtualFile.js";
|
||||
import styles from "./TextEditor.module.css";
|
||||
import { HeaderMenu } from "../.common/HeaderMenu.jsx";
|
||||
import Markdown from "markdown-to-jsx";
|
||||
import Application from "../../../features/applications/application.js";
|
||||
import { DEFAULT_ZOOM, ZOOM_FACTOR } from "../../../constants/applications/textEditor.js";
|
||||
import AppsManager from "../../../features/applications/applications.js";
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {VirtualFile} props.file
|
||||
* @param {Function} props.setTitle
|
||||
* @param {Function} props.close
|
||||
* @param {string} props.mode
|
||||
* @param {Application} props.app
|
||||
* @param {Function} props.setIconUrl
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
*/
|
||||
export function TextEditor({ file, setTitle, setIconUrl, close, mode, app }) {
|
||||
const [currentFile, setCurrentFile] = useState(file);
|
||||
|
|
@ -40,7 +32,6 @@ export function TextEditor({ file, setTitle, setIconUrl, close, mode, app }) {
|
|||
}
|
||||
|
||||
const iconUrl = currentFile.getIconUrl();
|
||||
console.log(iconUrl);
|
||||
if (iconUrl)
|
||||
setIconUrl(iconUrl);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { FALLBACK_WALLPAPER } from "../../constants/desktop.js";
|
|||
import { reloadViewport } from "../../features/utils/browser.js";
|
||||
import { useVirtualRoot } from "../../hooks/virtual-drive/virtualRootContext.js";
|
||||
import { DirectoryList } from "../applications/file-explorer/directory-list/DirectoryList.jsx";
|
||||
import { APPS } from "../../constants/applications.js";
|
||||
import { APPS, APP_NAMES } from "../../constants/applications.js";
|
||||
import Vector2 from "../../features/math/vector2.js";
|
||||
|
||||
export const Desktop = memo(() => {
|
||||
|
|
@ -20,12 +20,35 @@ export const Desktop = memo(() => {
|
|||
const [modalsManager, modals] = useModals();
|
||||
const windowsManager = useWindowsManager();
|
||||
const virtualRoot = useVirtualRoot();
|
||||
|
||||
const { onContextMenu } = useContextMenu({
|
||||
modalsManager,
|
||||
options: {
|
||||
"Refresh": () => { reloadViewport(); },
|
||||
"Change appearance": () => { windowsManager.open("settings", { initialTabIndex: 0 }); },
|
||||
"Open in Files": () => { windowsManager.open(APPS.FILE_EXPLORER, { startPath: "~/Desktop" }); },
|
||||
[`Open in ${APP_NAMES.FILE_EXPLORER}`]: () => {
|
||||
windowsManager.open(APPS.FILE_EXPLORER, { startPath: "~/Desktop" });
|
||||
},
|
||||
}
|
||||
});
|
||||
const { onContextMenu: onContextMenuFile } = useContextMenu({
|
||||
modalsManager,
|
||||
options: {
|
||||
"Open": (file) => { file.open(windowsManager); },
|
||||
[`Reveal in ${APP_NAMES.FILE_EXPLORER}`]: (file) => {
|
||||
windowsManager.open(APPS.FILE_EXPLORER, { startPath: file.parent.path });
|
||||
},
|
||||
"Delete": (file) => { file.delete(); },
|
||||
}
|
||||
});
|
||||
const { onContextMenu: onContextMenuFolder } = useContextMenu({
|
||||
modalsManager,
|
||||
options: {
|
||||
"Open": (folder) => { folder.open(windowsManager); },
|
||||
[`Reveal in ${APP_NAMES.FILE_EXPLORER}`]: (folder) => {
|
||||
windowsManager.open(APPS.FILE_EXPLORER, { startPath: folder.parent.path });
|
||||
},
|
||||
"Delete": (folder) => { folder.delete(); },
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -68,6 +91,8 @@ export const Desktop = memo(() => {
|
|||
onClickFolder={(event, { linkedPath, path }) => {
|
||||
windowsManager.open(APPS.FILE_EXPLORER, { startPath: linkedPath ?? path });
|
||||
}}
|
||||
onContextMenuFile={onContextMenuFile}
|
||||
onContextMenuFolder={onContextMenuFolder}
|
||||
/>
|
||||
</div>
|
||||
{wallpaper
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ export function DialogBox({ modal, params }) {
|
|||
position={null}
|
||||
scale={1}
|
||||
bounds={{
|
||||
top: 0,
|
||||
bottom: screenHeight - 55,
|
||||
left: -modal.size.x + 85,
|
||||
right: screenWidth - 5
|
||||
top: -modal.position.y - 1,
|
||||
bottom: screenHeight - 55 - modal.position.y,
|
||||
left: -modal.size.x + 85 - modal.position.x,
|
||||
right: screenWidth - 5 - modal.position.x
|
||||
}}
|
||||
cancel="button"
|
||||
nodeRef={nodeRef}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@
|
|||
flex-direction: column;
|
||||
min-width: 300px;
|
||||
min-height: 150px;
|
||||
background-color: var(--background-color-c);
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: var(--window-box-shadow);
|
||||
background-color: var(--background-color-c) !important;
|
||||
resize: both;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,17 @@ import { ModalsView } from "../modals/ModalsView.jsx";
|
|||
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
||||
import AppsManager from "../../features/applications/applications.js";
|
||||
|
||||
/**
|
||||
* @typedef {object} windowProps
|
||||
* @property {Application} app
|
||||
* @property {Function} setTitle
|
||||
* @property {Function} setIconUrl
|
||||
* @property {Function} close
|
||||
* @property {Function} focus
|
||||
* @property {boolean} active
|
||||
* @property {import("../../features/modals/modals.js").default} modalsManager
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {object} props
|
||||
* @param {string} props.id
|
||||
|
|
@ -172,6 +183,7 @@ export const WindowView = memo(({ id, app, size, position, onInteract, options,
|
|||
close={close}
|
||||
focus={focus}
|
||||
active={active}
|
||||
modalsManager={modalsManager}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,4 +4,12 @@ export const APPS = {
|
|||
MEDIA_VIEWER: "media-viewer",
|
||||
TEXT_EDITOR: "text-editor",
|
||||
FILE_EXPLORER: "file-explorer"
|
||||
};
|
||||
|
||||
export const APP_NAMES = {
|
||||
TERMINAL: "Commands",
|
||||
SETTINGS: "Settings",
|
||||
MEDIA_VIEWER: "Photos",
|
||||
TEXT_EDITOR: "Notes",
|
||||
FILE_EXPLORER: "Files"
|
||||
};
|
||||
|
|
@ -42,11 +42,11 @@ export default class ModalsManager {
|
|||
modalId = modalId.toString();
|
||||
|
||||
if (!this.modalIds.includes(modalId)) {
|
||||
console.log(`Failed to close modal ${modalId}: modal not found`);
|
||||
console.warn(`Failed to close modal ${modalId}: modal not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Closing modal ${modalId}`);
|
||||
console.info(`Closing modal ${modalId}`);
|
||||
delete this.modals[modalId];
|
||||
|
||||
if (sendModalsUpdate)
|
||||
|
|
@ -60,7 +60,7 @@ export default class ModalsManager {
|
|||
modalId = modalId.toString();
|
||||
|
||||
if (!this.modalIds.includes(modalId)) {
|
||||
console.log(`Failed to focus modal ${modalId}: modal not found`);
|
||||
console.warn(`Failed to focus modal ${modalId}: modal not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,11 @@ export class VirtualFileLink extends VirtualFile {
|
|||
return this.isValid() ? this.linkedFile.id : null;
|
||||
}
|
||||
|
||||
/** @type {VirtualFile["open"]} */
|
||||
open(...args) {
|
||||
if (this.isValid()) return this.linkedFile.open(...args);
|
||||
}
|
||||
|
||||
/** @type {VirtualFile["read"]} */
|
||||
read(...args) {
|
||||
if (this.isValid()) return this.linkedFile.read(...args);
|
||||
|
|
|
|||
|
|
@ -130,4 +130,9 @@ export class VirtualFolderLink extends VirtualFolder {
|
|||
getSubFolders(...args) {
|
||||
if (this.isValid()) return this.linkedFolder.getSubFolders(...args);
|
||||
}
|
||||
|
||||
/** @type {VirtualFolder["open"]} */
|
||||
open(...args) {
|
||||
if (this.isValid()) return this.linkedFolder.open(...args);
|
||||
}
|
||||
}
|
||||
|
|
@ -94,8 +94,6 @@ export class VirtualBase extends EventEmitter {
|
|||
if (!this.canBeEdited)
|
||||
return;
|
||||
|
||||
console.log(this);
|
||||
|
||||
const parent = this.parent;
|
||||
|
||||
if (parent == null)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import WindowsManager from "../windows/windows.js";
|
||||
import { VirtualBase } from "./virtualBase.js";
|
||||
|
||||
/**
|
||||
|
|
@ -72,6 +73,14 @@ export class VirtualFile extends VirtualBase {
|
|||
return `${this.name}.${this.extension}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens this file in an app associated with its extension
|
||||
* @param {WindowsManager} windowsManager
|
||||
*/
|
||||
open(windowsManager) {
|
||||
return windowsManager.openFile(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<string | null>}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { APPS } from "../../constants/applications.js";
|
||||
import { removeFromArray } from "../utils/array.js";
|
||||
import WindowsManager from "../windows/windows.js";
|
||||
import { VirtualFileLink } from "./VirtualFileLink.js";
|
||||
import { VirtualFolderLink } from "./VirtualFolderLink.js";
|
||||
import { VirtualBase } from "./virtualBase.js";
|
||||
|
|
@ -339,6 +341,14 @@ export class VirtualFolder extends VirtualBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens this folder in file explorer
|
||||
* @param {WindowsManager} windowsManager
|
||||
*/
|
||||
open(windowsManager) {
|
||||
return windowsManager.open(APPS.FILE_EXPLORER, { startPath: this.path });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this folder and all its files and sub-folders recursively
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default class WindowsManager {
|
|||
|
||||
id = id.toString();
|
||||
|
||||
console.log(`Opening window ${id}:${app.id}`);
|
||||
console.info(`Opening window ${id}:${app.id}`);
|
||||
|
||||
this.windows[id] = {
|
||||
id,
|
||||
|
|
@ -56,7 +56,7 @@ export default class WindowsManager {
|
|||
* @returns {object}
|
||||
*/
|
||||
openFile(file, options = {}) {
|
||||
const app = AppsManager.getFileApp(file.extension);
|
||||
const app = AppsManager.getFileApp(file?.extension);
|
||||
if (app != null)
|
||||
return this.open(app.id, { file, ...options });
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ export default class WindowsManager {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log(`Closing window ${windowId}`);
|
||||
console.info(`Closing window ${windowId}`);
|
||||
delete this.windows[windowId];
|
||||
|
||||
this.updateWindows(this.windows);
|
||||
|
|
@ -22,6 +22,9 @@ import { useShortcuts } from "../utils/keyboard.js";
|
|||
export function useContextMenu({ modalsManager, options, shortcuts }) {
|
||||
// Open a new modal when context menu is triggered
|
||||
const onContextMenu = useCallback((event, params = {}) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
let positionX = (event?.clientX ?? 0);
|
||||
let positionY = (event?.clientY ?? 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ export function WindowsProvider({ children, windowsManager }) {
|
|||
const [windows, setWindows] = useState([]);
|
||||
|
||||
const updateWindows = useCallback((updatedWindows) => {
|
||||
// console.log(updatedWindows);
|
||||
setWindows(Object.values(updatedWindows));
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { createContext, useContext } from "react";
|
||||
import WindowsManager from "../../features/windows/windowsManager.js";
|
||||
import WindowsManager from "../../features/windows/windows.js";
|
||||
import { WindowsProvider } from "./windowsContext.js";
|
||||
|
||||
const WindowsManagerContext = createContext();
|
||||
|
|
|
|||
Loading…
Reference in a new issue