import { Icon } from "@iconify/react/dist/iconify.js"; import { Box, IconButton, InputAdornment, ListItemText, Table, TableBody, TableContainer, TableHead, TableRow, Typography, } from "@mui/material"; import { styled, useTheme } from "@mui/material/styles"; import { memo, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { DenseFilledTextField, DenseSelect, NoWrapCell, NoWrapTableCell, SecondaryButton, StyledTableContainerPaper, } from "../../../Common/StyledComponents.tsx"; import { SquareMenuItem } from "../../../FileManager/ContextMenu/ContextMenu.tsx"; import { builtInIcons, FileTypeIconSetting } from "../../../FileManager/Explorer/FileTypeIcon.tsx"; import Add from "../../../Icons/Add.tsx"; import Dismiss from "../../../Icons/Dismiss.tsx"; import HexColorInput from "../HexColorInput.tsx"; export interface FileIconListProps { config: string; onChange: (value: string) => void; } export enum IconType { Image = "imageUrl", Iconify = "iconifyName", } const StyledDenseSelect = styled(DenseSelect)(() => ({ "& .MuiFilledInput-input": { "&:focus": { backgroundColor: "initial", }, }, backgroundColor: "initial", })); const IconPreview = ({ icon }: { icon: FileTypeIconSetting }) => { const theme = useTheme(); const IconComponent = useMemo(() => { if (icon.icon) { return builtInIcons[icon.icon]; } }, [icon.icon]); const iconColor = useMemo(() => { if (theme.palette.mode == "dark") { return icon.color_dark ?? icon.color ?? theme.palette.action.active; } else { return icon.color ?? theme.palette.action.active; } }, [icon.color, icon.color_dark, theme]); if (IconComponent) { return ( ); } // Handle iconify icons if (icon.iconify) { return ; } return ( ); }; const FileIconList = memo(({ config, onChange }: FileIconListProps) => { const { t } = useTranslation("dashboard"); const configParsed = useMemo((): FileTypeIconSetting[] => JSON.parse(config), [config]); const [inputCache, setInputCache] = useState<{ [key: number]: string | undefined; }>({}); const [iconUrlCache, setIconUrlCache] = useState<{ [key: number]: string | undefined; }>({}); const [iconTypeCache, setIconTypeCache] = useState<{ [key: number]: IconType | undefined; }>({}); return ( {configParsed?.length > 0 && ( {t("settings.icon")} {t("settings.iconUrl")} {t("settings.iconColor")} {t("settings.iconColorDark")} {t("settings.exts")} {configParsed.map((r, i) => { const currentIconType = iconTypeCache[i] ?? (r.img ? IconType.Image : r.iconify ? IconType.Iconify : IconType.Image); const currentIconUrl = iconUrlCache[i] ?? (currentIconType === IconType.Image ? r.img : r.iconify) ?? ""; return ( {!r.icon ? ( { const newConfig = [...configParsed]; const updatedItem = { ...r }; if (currentIconType === IconType.Image) { updatedItem.img = currentIconUrl; updatedItem.iconify = undefined; } else { updatedItem.iconify = currentIconUrl; updatedItem.img = undefined; } newConfig[i] = updatedItem; onChange(JSON.stringify(newConfig)); setIconUrlCache({ ...iconUrlCache, [i]: undefined, }); }} onChange={(e) => setIconUrlCache({ ...iconUrlCache, [i]: e.target.value, }) } slotProps={{ input: { startAdornment: ( { const newType = e.target.value as IconType; setIconTypeCache({ ...iconTypeCache, [i]: newType, }); // Clear the URL cache when switching types setIconUrlCache({ ...iconUrlCache, [i]: "", }); // Update the config immediately const newConfig = [...configParsed]; const updatedItem = { ...r }; if (newType === IconType.Image) { updatedItem.img = ""; updatedItem.iconify = undefined; } else { updatedItem.iconify = ""; updatedItem.img = undefined; } newConfig[i] = updatedItem; onChange(JSON.stringify(newConfig)); }} renderValue={(value) => ( {t(`settings.${value}`)} )} size={"small"} variant="filled" > {t(`settings.${IconType.Image}`)} {t(`settings.${IconType.Iconify}`)} ), }, }} /> ) : ( t("settings.builtinIcon") )} {!r.icon && !r.iconify ? ( "-" ) : ( onChange( JSON.stringify([ ...configParsed.slice(0, i), { ...r, color: color, }, ...configParsed.slice(i + 1), ]), ) } /> )} {!r.icon && !r.iconify ? ( "-" ) : ( onChange( JSON.stringify([ ...configParsed.slice(0, i), { ...r, color_dark: color, }, ...configParsed.slice(i + 1), ]), ) } /> )} { onChange( JSON.stringify([ ...configParsed.slice(0, i), { ...r, exts: inputCache[i]?.split(",") ?? r.exts, }, ...configParsed.slice(i + 1), ]), ); setInputCache({ ...inputCache, [i]: undefined, }); }} onChange={(e) => setInputCache({ ...inputCache, [i]: e.target.value, }) } /> {!r.icon && ( onChange(JSON.stringify(configParsed.filter((_, index) => index !== i)))} size={"small"} > )} ); })}
)} } sx={{ mt: 1 }} onClick={() => onChange( JSON.stringify([ ...configParsed, { img: "", exts: [], }, ]), ) } > {t("settings.addIcon")}
); }); export default FileIconList;