Added file explorer history navigation
This commit is contained in:
parent
7334b6ceb5
commit
e19d284a91
3 changed files with 97 additions and 17 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useVirtualRoot } from "../../../hooks/virtual-drive/virtualRootContext.js";
|
||||
import styles from "./FileExplorer.module.css";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
|
@ -18,6 +18,7 @@ import AppsManager from "../../../features/applications/applications.js";
|
|||
import { APPS } from "../../../constants/applications.js";
|
||||
import { TITLE_SEPARATOR } from "../../../constants/windows.js";
|
||||
import { FileProperties } from "../../modals/file-properties/FileProperties.jsx";
|
||||
import { useHistory } from "../../../hooks/utils/history.js";
|
||||
|
||||
/**
|
||||
* @param {import("../../windows/WindowView.jsx").windowProps} props
|
||||
|
|
@ -28,6 +29,7 @@ export function FileExplorer({ startPath, app, modalsManager }) {
|
|||
const [path, setPath] = useState(currentDirectory?.path ?? "");
|
||||
const windowsManager = useWindowsManager();
|
||||
const [showHidden] = useState(true);
|
||||
const { history, stateIndex, pushState, undo, redo, undoAvailable, redoAvailable } = useHistory(currentDirectory.path);
|
||||
|
||||
const { openWindowedModal } = useWindowedModal({ modalsManager });
|
||||
const { onContextMenu: onContextMenuFile } = useContextMenu({ modalsManager, Actions: (props) =>
|
||||
|
|
@ -46,15 +48,6 @@ export function FileExplorer({ startPath, app, modalsManager }) {
|
|||
Modal: (props) =>
|
||||
<FileProperties file={file} {...props}/>
|
||||
});
|
||||
// modalsManager.open(new Modal(FileProperties)
|
||||
// .setPosition(new Vector2(positionX, positionY))
|
||||
// .setProps({
|
||||
// triggerParams: params,
|
||||
// className: STYLES.CONTEXT_MENU,
|
||||
// onAnyTrigger: () => {
|
||||
// newModal.close();
|
||||
// }
|
||||
// }));
|
||||
}}/>
|
||||
</Actions>
|
||||
});
|
||||
|
|
@ -76,7 +69,10 @@ export function FileExplorer({ startPath, app, modalsManager }) {
|
|||
// }
|
||||
// });
|
||||
|
||||
const changeDirectory = (path, absolute = false) => {
|
||||
const changeDirectory = useCallback((path, absolute = false) => {
|
||||
if (path == null)
|
||||
return;
|
||||
|
||||
if (currentDirectory == null)
|
||||
absolute = true;
|
||||
|
||||
|
|
@ -84,14 +80,27 @@ export function FileExplorer({ startPath, app, modalsManager }) {
|
|||
|
||||
console.debug(directory);
|
||||
|
||||
if (directory) {
|
||||
if (directory != null) {
|
||||
setCurrentDirectory(directory);
|
||||
setPath(directory.root ? "/" : directory.path);
|
||||
pushState(directory.path);
|
||||
}
|
||||
}, [currentDirectory, pushState, virtualRoot]);
|
||||
|
||||
useEffect(() => {
|
||||
if (history.length === 0)
|
||||
return;
|
||||
|
||||
const path = history[stateIndex];
|
||||
const directory = virtualRoot.navigate(path);
|
||||
if (directory != null) {
|
||||
setCurrentDirectory(directory);
|
||||
setPath(directory.root ? "/" : directory.path);
|
||||
}
|
||||
};
|
||||
}, [history, stateIndex, virtualRoot]);
|
||||
|
||||
const onPathChange = (event) => {
|
||||
return setPath(event.target.value);
|
||||
setPath(event.target.value);
|
||||
};
|
||||
|
||||
const onKeyDown = (event) => {
|
||||
|
|
@ -113,10 +122,22 @@ export function FileExplorer({ startPath, app, modalsManager }) {
|
|||
return (
|
||||
<div className={styles.Container}>
|
||||
<div className={styles.Header}>
|
||||
<button title="Back" tabIndex={0} className={styles["Icon-button"]}>
|
||||
<button
|
||||
title="Back"
|
||||
tabIndex={0}
|
||||
className={styles["Icon-button"]}
|
||||
onClick={undo}
|
||||
disabled={!undoAvailable}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCaretLeft}/>
|
||||
</button>
|
||||
<button title="Forward" tabIndex={0} className={styles["Icon-button"]}>
|
||||
<button
|
||||
title="Forward"
|
||||
tabIndex={0}
|
||||
className={styles["Icon-button"]}
|
||||
onClick={redo}
|
||||
disabled={!redoAvailable}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCaretRight}/>
|
||||
</button>
|
||||
<button title="Up" tabIndex={0} className={styles["Icon-button"]} onClick={() => { changeDirectory(".."); }}>
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@
|
|||
}
|
||||
|
||||
.Icon-button {
|
||||
--color: var(--foreground-color-a);
|
||||
|
||||
position: relative;
|
||||
height: 1.25rem;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
color: var(--foreground-a);
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
|
|
@ -51,10 +52,19 @@
|
|||
transform: scale(150%);
|
||||
}
|
||||
|
||||
.Icon-button:disabled {
|
||||
--color: var(--foreground-color-c);
|
||||
}
|
||||
|
||||
.Icon-button svg {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.Icon-button svg path {
|
||||
fill: var(--color);
|
||||
transition: fill 100ms ease-in-out;
|
||||
}
|
||||
|
||||
.Path-input {
|
||||
flex: 1;
|
||||
padding: 0.25rem 0.5rem;
|
||||
|
|
|
|||
49
src/hooks/utils/history.js
Normal file
49
src/hooks/utils/history.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { useState } from "react";
|
||||
import { clamp } from "../../features/math/clamp.js";
|
||||
|
||||
/**
|
||||
* @param {*} initialState
|
||||
* @returns {{
|
||||
* history: *[],
|
||||
* stateIndex: number,
|
||||
* pushState: Function,
|
||||
* undo: Function,
|
||||
* redo: Function,
|
||||
* undoAvailable: boolean,
|
||||
* redoAvailable: boolean
|
||||
* }}
|
||||
*/
|
||||
export function useHistory(initialState) {
|
||||
const [history, setHistory] = useState(initialState ? [initialState] : []);
|
||||
const [stateIndex, setStateIndex] = useState(0);
|
||||
|
||||
const pushState = (state) => {
|
||||
if (state === history[0])
|
||||
return;
|
||||
|
||||
const newHistory = [
|
||||
state,
|
||||
...history.slice(stateIndex, history.length)
|
||||
];
|
||||
|
||||
setHistory(newHistory);
|
||||
setStateIndex(0);
|
||||
};
|
||||
|
||||
const updateStateIndex = (delta) => {
|
||||
const index = clamp(stateIndex + delta, 0, history.length - 1);
|
||||
|
||||
if (index === stateIndex)
|
||||
return;
|
||||
|
||||
setStateIndex(index);
|
||||
};
|
||||
|
||||
const undo = () => updateStateIndex(1);
|
||||
const redo = () => updateStateIndex(-1);
|
||||
|
||||
const undoAvailable = (stateIndex < history.length - 1);
|
||||
const redoAvailable = (stateIndex >= 1);
|
||||
|
||||
return { history, stateIndex, pushState, undo, redo, undoAvailable, redoAvailable };
|
||||
}
|
||||
Loading…
Reference in a new issue