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;