mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2026-01-15 12:15:02 +00:00
This commit is contained in:
@@ -23,16 +23,19 @@ import {
|
||||
import useResizeObserver from "hooks/useResizeObserver";
|
||||
|
||||
type NavigationProps = {
|
||||
addressBarRef: React.RefObject<HTMLInputElement | null>;
|
||||
hideSearch: boolean;
|
||||
id: string;
|
||||
searchBarRef: React.RefObject<HTMLInputElement | null>;
|
||||
};
|
||||
|
||||
const CONTEXT_MENU_OFFSET = 3;
|
||||
|
||||
const Navigation: FCWithRef<HTMLInputElement, NavigationProps> = ({
|
||||
const Navigation: FC<NavigationProps> = ({
|
||||
hideSearch,
|
||||
id,
|
||||
ref: inputRef,
|
||||
addressBarRef,
|
||||
searchBarRef,
|
||||
}) => {
|
||||
const {
|
||||
url: changeUrl,
|
||||
@@ -149,8 +152,8 @@ const Navigation: FCWithRef<HTMLInputElement, NavigationProps> = ({
|
||||
>
|
||||
<Up />
|
||||
</Button>
|
||||
<AddressBar ref={inputRef} id={id} />
|
||||
{!hideSearch && !removeSearch && <SearchBar id={id} />}
|
||||
<AddressBar ref={addressBarRef} id={id} />
|
||||
{!hideSearch && !removeSearch && <SearchBar ref={searchBarRef} id={id} />}
|
||||
</StyledNavigation>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,10 @@ type SearchBarProps = {
|
||||
|
||||
const MAX_ENTRIES = 10;
|
||||
|
||||
const SearchBar: FC<SearchBarProps> = ({ id }) => {
|
||||
const SearchBar: FCWithRef<HTMLInputElement, SearchBarProps> = ({
|
||||
id,
|
||||
ref: searchBarRef,
|
||||
}) => {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const hasUsedSearch = useRef(false);
|
||||
const {
|
||||
@@ -32,14 +35,13 @@ const SearchBar: FC<SearchBarProps> = ({ id }) => {
|
||||
[id]: { url = "" },
|
||||
},
|
||||
} = useProcesses();
|
||||
const searchBarRef = useRef<HTMLInputElement | null>(null);
|
||||
const results = useSearch(searchTerm);
|
||||
const { contextMenu } = useMenu();
|
||||
const { fs } = useFileSystem();
|
||||
const { updateRecentFiles } = useSession();
|
||||
|
||||
useEffect(() => {
|
||||
if (searchBarRef.current && hasUsedSearch.current) {
|
||||
if (searchBarRef?.current && hasUsedSearch.current) {
|
||||
const getItems = (): Promise<MenuItem[]> =>
|
||||
Promise.all(
|
||||
[
|
||||
@@ -59,7 +61,8 @@ const SearchBar: FC<SearchBarProps> = ({ id }) => {
|
||||
open(pid, { url: infoUrl });
|
||||
setSearchTerm("");
|
||||
|
||||
if (searchBarRef.current) {
|
||||
if (searchBarRef?.current) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
searchBarRef.current.value = "";
|
||||
searchBarRef.current.blur();
|
||||
}
|
||||
@@ -84,15 +87,16 @@ const SearchBar: FC<SearchBarProps> = ({ id }) => {
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [contextMenu, fs, open, results, updateRecentFiles, url]);
|
||||
}, [contextMenu, fs, open, results, searchBarRef, updateRecentFiles, url]);
|
||||
|
||||
useEffect(() => {
|
||||
if (searchBarRef.current) {
|
||||
if (searchBarRef?.current) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
searchBarRef.current.value = "";
|
||||
setSearchTerm("");
|
||||
}
|
||||
// eslint-disable-next-line react-hooks-addons/no-unused-deps
|
||||
}, [url]);
|
||||
}, [searchBarRef, url]);
|
||||
|
||||
return (
|
||||
<StyledSearch>
|
||||
|
||||
@@ -27,13 +27,22 @@ const FileExplorer: FC<ComponentProcessProps> = ({ id }) => {
|
||||
const { componentWindow, closing, icon = "", url = "" } = process || {};
|
||||
const { fs, rootFs } = useFileSystem();
|
||||
const [currentUrl, setCurrentUrl] = useState(url);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const addressBarRef = useRef<HTMLInputElement | null>(null);
|
||||
const searchBarRef = useRef<HTMLInputElement | null>(null);
|
||||
const directoryName = basename(url);
|
||||
const mountUrl = getMountUrl(url, rootFs?.mntMap || {});
|
||||
const onKeyDown = useCallback((event: KeyboardEvent): void => {
|
||||
if (event.altKey && event.key.toUpperCase() === "D") {
|
||||
const eventKey = event.key.toUpperCase();
|
||||
|
||||
if (event.altKey && eventKey === "D") {
|
||||
haltEvent(event);
|
||||
inputRef.current?.focus(PREVENT_SCROLL);
|
||||
addressBarRef.current?.focus(PREVENT_SCROLL);
|
||||
} else if (
|
||||
eventKey === "F3" ||
|
||||
(event.ctrlKey && (eventKey === "E" || eventKey === "F"))
|
||||
) {
|
||||
haltEvent(event);
|
||||
searchBarRef.current?.focus(PREVENT_SCROLL);
|
||||
} else {
|
||||
const fileManagerEntry = (event?.target as HTMLElement)?.querySelector(
|
||||
"ol li button"
|
||||
@@ -102,14 +111,24 @@ const FileExplorer: FC<ComponentProcessProps> = ({ id }) => {
|
||||
}, [closing, id, componentWindow, setProcessIcon, setProcessUrl, url]);
|
||||
|
||||
useEffect(() => {
|
||||
componentWindow?.addEventListener("keydown", onKeyDown);
|
||||
componentWindow?.addEventListener("keydown", onKeyDown, {
|
||||
capture: true,
|
||||
});
|
||||
|
||||
return () => componentWindow?.removeEventListener("keydown", onKeyDown);
|
||||
return () =>
|
||||
componentWindow?.removeEventListener("keydown", onKeyDown, {
|
||||
capture: true,
|
||||
});
|
||||
}, [componentWindow, onKeyDown]);
|
||||
|
||||
return url ? (
|
||||
<StyledFileExplorer>
|
||||
<Navigation ref={inputRef} hideSearch={Boolean(mountUrl)} id={id} />
|
||||
<Navigation
|
||||
addressBarRef={addressBarRef}
|
||||
hideSearch={Boolean(mountUrl)}
|
||||
id={id}
|
||||
searchBarRef={searchBarRef}
|
||||
/>
|
||||
<FileManager id={id} url={url} showStatusBar />
|
||||
</StyledFileExplorer>
|
||||
) : // eslint-disable-next-line unicorn/no-null
|
||||
|
||||
@@ -242,7 +242,7 @@ const FileManager: FC<FileManagerProps> = ({
|
||||
ref={fileManagerRef}
|
||||
$isEmptyFolder={isEmptyFolder}
|
||||
$scrollable={!hideScrolling}
|
||||
onKeyDown={onKeyDown}
|
||||
onKeyDownCapture={onKeyDown}
|
||||
{...(readOnly
|
||||
? { onContextMenu: haltEvent }
|
||||
: {
|
||||
|
||||
@@ -31,7 +31,7 @@ const useFileKeyboardShortcuts = (
|
||||
setView?: (newView: FileManagerViewNames) => void
|
||||
): KeyboardShortcutEntry => {
|
||||
const { copyEntries, deletePath, moveEntries } = useFileSystem();
|
||||
const { url: changeUrl } = useProcesses();
|
||||
const { open, url: changeUrl } = useProcesses();
|
||||
const { openTransferDialog } = useTransferDialog();
|
||||
const { foregroundId } = useSession();
|
||||
|
||||
@@ -58,7 +58,7 @@ const useFileKeyboardShortcuts = (
|
||||
(event) => {
|
||||
if (isStartMenu) return;
|
||||
|
||||
const { ctrlKey, key, target, shiftKey } = event;
|
||||
const { altKey, ctrlKey, key, target, shiftKey } = event;
|
||||
|
||||
if (shiftKey) {
|
||||
if (ctrlKey && !isDesktop) {
|
||||
@@ -85,6 +85,18 @@ const useFileKeyboardShortcuts = (
|
||||
return;
|
||||
}
|
||||
|
||||
const onDelete = (): void => {
|
||||
if (focusedEntries.length > 0) {
|
||||
haltEvent(event);
|
||||
focusedEntries.forEach(async (entry) => {
|
||||
const path = join(url, entry);
|
||||
|
||||
if (await deletePath(path)) updateFiles(undefined, path);
|
||||
});
|
||||
blurEntry();
|
||||
}
|
||||
};
|
||||
|
||||
if (ctrlKey) {
|
||||
const lKey = key.toLowerCase();
|
||||
|
||||
@@ -103,6 +115,13 @@ const useFileKeyboardShortcuts = (
|
||||
haltEvent(event);
|
||||
copyEntries(focusedEntries.map((entry) => join(url, entry)));
|
||||
break;
|
||||
case "d":
|
||||
onDelete();
|
||||
break;
|
||||
case "r":
|
||||
haltEvent(event);
|
||||
updateFiles();
|
||||
break;
|
||||
case "x":
|
||||
haltEvent(event);
|
||||
moveEntries(focusedEntries.map((entry) => join(url, entry)));
|
||||
@@ -114,6 +133,16 @@ const useFileKeyboardShortcuts = (
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (altKey) {
|
||||
const lKey = key.toLowerCase();
|
||||
|
||||
if (lKey === "n") {
|
||||
haltEvent(event);
|
||||
open("FileExplorer", { url });
|
||||
} else if (key === "Enter" && focusedEntries.length > 0) {
|
||||
haltEvent(event);
|
||||
open("Properties", { url: join(url, focusedEntries[0]) });
|
||||
}
|
||||
} else {
|
||||
switch (key) {
|
||||
case "F2":
|
||||
@@ -129,15 +158,7 @@ const useFileKeyboardShortcuts = (
|
||||
}
|
||||
break;
|
||||
case "Delete":
|
||||
if (focusedEntries.length > 0) {
|
||||
haltEvent(event);
|
||||
focusedEntries.forEach(async (entry) => {
|
||||
const path = join(url, entry);
|
||||
|
||||
if (await deletePath(path)) updateFiles(undefined, path);
|
||||
});
|
||||
blurEntry();
|
||||
}
|
||||
onDelete();
|
||||
break;
|
||||
case "Backspace":
|
||||
if (id) {
|
||||
@@ -263,6 +284,7 @@ const useFileKeyboardShortcuts = (
|
||||
isDesktop,
|
||||
isStartMenu,
|
||||
moveEntries,
|
||||
open,
|
||||
pasteToFolder,
|
||||
setRenaming,
|
||||
setView,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useProcesses } from "contexts/process";
|
||||
import { useSession } from "contexts/session";
|
||||
import Button from "styles/common/Button";
|
||||
import Icon from "styles/common/Icon";
|
||||
import { DIV_BUTTON_PROPS } from "utils/constants";
|
||||
import { DIV_BUTTON_PROPS, PROCESS_DELIMITER } from "utils/constants";
|
||||
import { isSafari, label } from "utils/functions";
|
||||
|
||||
const PeekWindow = dynamic(
|
||||
@@ -29,9 +29,10 @@ const TaskbarEntry: FC<TaskbarEntryProps> = ({ icon, id, title }) => {
|
||||
const {
|
||||
linkElement,
|
||||
minimize,
|
||||
open,
|
||||
processes: { [id]: process },
|
||||
} = useProcesses();
|
||||
const { minimized, progress } = process || {};
|
||||
const { minimized, progress, singleton } = process || {};
|
||||
const linkTaskbarEntry = useCallback(
|
||||
(taskbarEntry: HTMLButtonElement | HTMLDivElement | null) => {
|
||||
if (taskbarEntry) linkElement(id, "taskbarEntry", taskbarEntry);
|
||||
@@ -41,11 +42,29 @@ const TaskbarEntry: FC<TaskbarEntryProps> = ({ icon, id, title }) => {
|
||||
const [isPeekVisible, setIsPeekVisible] = useState(false);
|
||||
const hidePeek = useCallback((): void => setIsPeekVisible(false), []);
|
||||
const showPeek = useCallback((): void => setIsPeekVisible(true), []);
|
||||
const onClick = useCallback((): void => {
|
||||
if (minimized || isForeground) minimize(id);
|
||||
const onClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
|
||||
(event): void => {
|
||||
if (event.shiftKey && !singleton) {
|
||||
const [pid] = id.split(PROCESS_DELIMITER);
|
||||
|
||||
setForegroundId(isForeground ? nextFocusableId : id);
|
||||
}, [id, isForeground, minimize, minimized, nextFocusableId, setForegroundId]);
|
||||
open(pid);
|
||||
} else {
|
||||
if (minimized || isForeground) minimize(id);
|
||||
|
||||
setForegroundId(isForeground ? nextFocusableId : id);
|
||||
}
|
||||
},
|
||||
[
|
||||
id,
|
||||
isForeground,
|
||||
minimize,
|
||||
minimized,
|
||||
nextFocusableId,
|
||||
open,
|
||||
setForegroundId,
|
||||
singleton,
|
||||
]
|
||||
);
|
||||
const focusable = useMemo(() => (isSafari() ? DIV_BUTTON_PROPS : {}), []);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user