securityos/components/apps/FileExplorer/SearchBar.tsx

95 lines
2.8 KiB
TypeScript

import { Search } from "components/apps/FileExplorer/NavigationIcons";
import StyledSearch from "components/apps/FileExplorer/StyledSearch";
import { TEXT_EDITORS } from "components/system/Files/FileEntry/extensions";
import {
getIconByFileExtension,
getProcessByFileExtension,
} from "components/system/Files/FileEntry/functions";
import { useMenu } from "contexts/menu";
import type { MenuItem } from "contexts/menu/useMenuContextState";
import { useProcesses } from "contexts/process";
import { basename, extname } from "path";
import { useEffect, useRef, useState } from "react";
import { preloadLibs } from "utils/functions";
import { SEARCH_LIBS, useSearch } from "utils/search";
type SearchBarProps = {
id: string;
};
const MAX_ENTRIES = 10;
const SearchBar: FC<SearchBarProps> = ({ id }) => {
const [searchTerm, setSearchTerm] = useState("");
const hasUsedSearch = useRef(false);
const {
open,
processes: {
[id]: { url = "" },
},
} = useProcesses();
const searchBarRef = useRef<HTMLInputElement | null>(null);
const results = useSearch(searchTerm);
const { contextMenu } = useMenu();
useEffect(() => {
if (searchBarRef.current && hasUsedSearch.current) {
const getItems = (): MenuItem[] =>
[
...results.filter(({ ref: path }) => path.startsWith(url)),
...results.filter(({ ref: path }) => !path.startsWith(url)),
]
.slice(0, MAX_ENTRIES - 1)
.map(({ ref: path }) => ({
action: () => {
open(
getProcessByFileExtension(extname(path)) || TEXT_EDITORS[0],
{ url: path }
);
setSearchTerm("");
if (searchBarRef.current) {
searchBarRef.current.value = "";
searchBarRef.current.blur();
}
},
icon: getIconByFileExtension(extname(path)),
label: basename(path),
}));
contextMenu?.(getItems).onContextMenuCapture(
undefined,
searchBarRef.current.getBoundingClientRect()
);
}
}, [contextMenu, open, results, url]);
useEffect(() => {
if (searchBarRef.current) {
searchBarRef.current.value = "";
setSearchTerm("");
}
}, [url]);
return (
<StyledSearch>
<Search />
<input
ref={searchBarRef}
aria-label="Search box"
enterKeyHint="search"
onChange={({ target }) => {
hasUsedSearch.current = true;
setSearchTerm(target.value);
}}
onFocus={() => preloadLibs(SEARCH_LIBS)}
placeholder="Search"
spellCheck={false}
type="text"
/>
</StyledSearch>
);
};
export default SearchBar;