Fixed bugs related to modals

This commit is contained in:
Prozilla 2023-12-13 12:07:41 +01:00
parent 75666e7135
commit d73db00326
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
20 changed files with 105 additions and 45 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -94,8 +94,6 @@ export class VirtualBase extends EventEmitter {
if (!this.canBeEdited)
return;
console.log(this);
const parent = this.parent;
if (parent == null)

View file

@ -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>}
*/

View file

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

View file

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

View file

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

View file

@ -12,7 +12,6 @@ export function WindowsProvider({ children, windowsManager }) {
const [windows, setWindows] = useState([]);
const updateWindows = useCallback((updatedWindows) => {
// console.log(updatedWindows);
setWindows(Object.values(updatedWindows));
}, []);

View file

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