diff --git a/components/system/Files/FileEntry/SubIcons.tsx b/components/system/Files/FileEntry/SubIcons.tsx new file mode 100644 index 00000000..321833e0 --- /dev/null +++ b/components/system/Files/FileEntry/SubIcons.tsx @@ -0,0 +1,98 @@ +import type { FileManagerViewNames } from "components/system/Files/Views"; +import { FileEntryIconSize } from "components/system/Files/Views"; +import { useMemo } from "react"; +import Icon from "styles/common/Icon"; +import { + FOLDER_BACK_ICON, + FOLDER_FRONT_ICON, + SHORTCUT_ICON, +} from "utils/constants"; + +type IconProps = { + icon: string; + name: string; + view: FileManagerViewNames; +}; + +type SubIconProps = IconProps & { + baseIcon: string; + index: number; +}; + +type SubIconsProps = IconProps & { + showShortcutIcon: boolean; + subIcons?: string[]; +}; + +const SubIcon: FC = ({ baseIcon, icon, index, name, view }) => { + const iconView = useMemo( + () => + FileEntryIconSize[ + ![SHORTCUT_ICON, FOLDER_FRONT_ICON].includes(icon) && + !icon.startsWith("blob:") + ? "sub" + : view + ], + [icon, view] + ); + const style = useMemo( + () => + baseIcon === FOLDER_BACK_ICON && icon !== FOLDER_FRONT_ICON + ? { + transform: `${ + index === 0 + ? "matrix(0, 1.8, 1.8, 0.2, 1.2, 2)" + : "matrix(0, 1.8, 1.2, 0.4, -4, 4)" + } scaleX(-1) scale(0.4) translateZ(0px)`, + } + : undefined, + [baseIcon, icon, index] + ); + + return ( + + ); +}; + +const SubIcons: FC = ({ + icon, + name, + showShortcutIcon, + subIcons, + view, +}) => { + const icons = useMemo( + () => + showShortcutIcon + ? subIcons?.filter((iconEntry) => iconEntry !== SHORTCUT_ICON) + : subIcons, + [showShortcutIcon, subIcons] + ); + const filteredSubIcons = useMemo( + () => icons?.filter((subIcon) => subIcon !== icon) || [], + [icon, icons] + ); + + return ( + <> + {filteredSubIcons.map((entryIcon, subIconIndex) => ( + + ))} + + ); +}; + +export default SubIcons; diff --git a/components/system/Files/FileEntry/index.tsx b/components/system/Files/FileEntry/index.tsx index d6957d3a..990d922d 100644 --- a/components/system/Files/FileEntry/index.tsx +++ b/components/system/Files/FileEntry/index.tsx @@ -3,6 +3,7 @@ import { getModifiedTime, getTextWrapData, } from "components/system/Files/FileEntry/functions"; +import SubIcons from "components/system/Files/FileEntry/SubIcons"; import useFile from "components/system/Files/FileEntry/useFile"; import useFileContextMenu from "components/system/Files/FileEntry/useFileContextMenu"; import useFileInfo from "components/system/Files/FileEntry/useFileInfo"; @@ -21,6 +22,7 @@ import { m as motion } from "framer-motion"; import useDoubleClick from "hooks/useDoubleClick"; import dynamic from "next/dynamic"; import { basename, dirname, extname, join } from "path"; +import type { CSSProperties } from "react"; import { useCallback, useEffect, @@ -34,18 +36,16 @@ import Button from "styles/common/Button"; import Icon from "styles/common/Icon"; import { DEFAULT_LOCALE, - FOLDER_BACK_ICON, - FOLDER_FRONT_ICON, ICON_CACHE, ICON_CACHE_EXTENSION, ICON_PATH, IMAGE_FILE_EXTENSIONS, + LIST_VIEW_ANIMATION, MOUNTABLE_EXTENSIONS, NON_BREAKING_HYPHEN, ONE_TIME_PASSIVE_EVENT, PREVENT_SCROLL, SHORTCUT_EXTENSION, - SHORTCUT_ICON, SMALLEST_PNG_SIZE, USER_ICON_PATH, VIDEO_FILE_EXTENSIONS, @@ -159,15 +159,13 @@ const FileEntry: FC = ({ const figureRef = useRef(null); const fileName = basename(path); const urlExt = extname(url).toLowerCase(); - const isDynamicIcon = - IMAGE_FILE_EXTENSIONS.has(urlExt) || - VIDEO_FILE_EXTENSIONS.has(urlExt) || - isYouTubeUrl(url); - const filteredSubIcons = ( - hideShortcutIcon || stats.systemShortcut - ? subIcons?.filter((iconEntry) => iconEntry !== SHORTCUT_ICON) - : subIcons - )?.filter((subIcon) => subIcon !== icon); + const isDynamicIcon = useMemo( + () => + IMAGE_FILE_EXTENSIONS.has(urlExt) || + VIDEO_FILE_EXTENSIONS.has(urlExt) || + isYouTubeUrl(url), + [url, urlExt] + ); const isOnlyFocusedEntry = focusedEntries.length === 1 && focusedEntries[0] === fileName; const extension = extname(path).toLowerCase(); @@ -243,10 +241,40 @@ const FileEntry: FC = ({ url, ]); const [tooltip, setTooltip] = useState(); + const doubleClickHandler = useCallback(() => { + if ( + openInFileExplorer && + fileManagerId && + !MOUNTABLE_EXTENSIONS.has(urlExt) + ) { + changeUrl(fileManagerId, url); + blurEntry(); + } else if (openInFileExplorer && listView) { + setShowInFileManager((currentState) => !currentState); + } else { + openFile(pid, !isDynamicIcon ? icon : undefined); + } + }, [ + blurEntry, + changeUrl, + fileManagerId, + icon, + isDynamicIcon, + listView, + openFile, + openInFileExplorer, + pid, + url, + urlExt, + ]); + const style = useMemo( + () => (renaming ? ({ pointerEvents: "all" } as CSSProperties) : undefined), + [renaming] + ); useEffect(() => { - const updateIcon = async (): Promise => { - if (!isLoadingFileManager && !isIconCached.current) { + if (!isLoadingFileManager && !isIconCached.current) { + const updateIcon = async (): Promise => { if (icon.startsWith("blob:") || icon.startsWith("data:")) { if (icon.startsWith("data:image/jpeg;base64,")) return; @@ -369,10 +397,10 @@ const FileEntry: FC = ({ ).observe(buttonRef.current); } } - } - }; + }; - updateIcon(); + updateIcon(); + } }, [ exists, fileManagerRef, @@ -449,30 +477,12 @@ const FileEntry: FC = ({ return ( <>