enzostvs's picture
enzostvs HF Staff
Update components/editor-icons/index.tsx
f0fd9a7 verified
import { useContext, useState } from "react";
import Image from "next/image";
import { useTour } from "@reactour/tour";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faDownload } from "@fortawesome/free-solid-svg-icons";
import saveAsPng from "save-svg-as-png";
import { EditorType, IconItem } from "types/editor";
import { Icon } from "./icon";
import { EditorTabs } from "components/editor-icons/comps/tabs";
import { ListIcons } from "components/editor-icons/comps/list";
import { Search } from "components/search";
import { ClydeMessage } from "components/clyde/message";
import { Switch } from "components/switch";
import { Shapes } from "@/components/editor-icons/comps/shapes";
import { Icons } from "components/editor-icons/comps/icons";
import { useUser } from "utils/auth";
import { PremiumContext } from "components/premium/premium";
import DefaultAvatar from "assets/images/avatars/default-avatar.svg";
import DefaultAvatar2 from "assets/images/avatars/default-avatar-2.svg";
import BackgroundTransparent from "assets/images/editor/transparent_bg.svg";
import { API } from "@/utils/api";
import { Premium } from "../premium";
import { FormattedMessage, useIntl } from "react-intl";
export default function Editor({
editor,
onChange,
}: {
editor: EditorType;
onChange: (e: EditorType) => void;
}) {
const intl = useIntl();
const { user } = useUser();
const { setOpen } = useContext(PremiumContext);
const { setIsOpen } = useTour();
const [currentTab, setCurrentTab] = useState(0);
const [multiIcons, setMultiIcons] = useState(false);
const [search, setSearch] = useState("");
const renderTabs = (currentTab: number) => {
switch (currentTab) {
case 0:
return (
<>
<Search search={search} setSearch={setSearch} />
<div className="flex items-center justify-start gap-2 mt-4 lg:mt-3 mb-5">
<Switch
value={multiIcons}
size="small"
onChange={!user?.id ? () => setOpen(true) : setMultiIcons}
/>
<p className="text-dark-100 text-sm font-semibold tracking-wider select-none flex items-center justify-start gap-2">
<FormattedMessage id="iconsEditor.editor.listIcons.multiIcons" />
{/* {!user?.id ? <Premium tooltip={false} /> : ""} */}
</p>
</div>
<ListIcons
onCustomText={() => {
// if (!user?.id) return setOpen(true);
onChange({
...editor,
icons: multiIcons
? [
...editor.icons,
{
colour: "#ffffff",
custom_text: {
enabled: true,
text: "10",
size: 160,
},
},
]
: [
{
...editor?.icons[0],
component: undefined,
position: undefined,
colour: "#ffffff",
custom_text: {
enabled: true,
text: "10",
size: 160,
},
},
],
});
if (!multiIcons) setCurrentTab(2);
}}
onCustomUpload={(image) => {
onChange({
...editor,
icons: multiIcons
? [
...editor.icons,
{
colour: "#ffffff",
image,
},
]
: [
{
...editor?.icons[0],
custom_text: undefined,
component: undefined,
position: undefined,
colour: "#ffffff",
image,
},
],
});
if (!multiIcons) setCurrentTab(2);
}}
onSelect={(icon: IconItem) => {
onChange({
...editor,
icons: multiIcons
? [
...editor.icons,
{
component: icon.name,
colour: icon?.defaultColor ?? "#fff",
},
]
: [
{
...editor?.icons[0],
colour: icon?.defaultColor ?? "#fff",
component: icon.name,
position: undefined,
custom_text: undefined,
},
],
});
}}
/>
</>
);
case 1:
return (
<>
<Shapes
editor={editor}
onChange={(newShape: any) =>
onChange({ ...editor, shape: { ...editor.shape, ...newShape } })
}
/>
</>
);
case 2:
return (
<>
<Icons
editor={editor}
onChange={onChange}
onStep={(tabIndex: number, allowMultiple?: boolean) => {
setCurrentTab(tabIndex);
setMultiIcons(user?.id ? allowMultiple || false : false);
}}
/>
</>
);
default:
return null;
}
};
const handleSaveIcon = () => {
const svg = document.getElementById("discotools-selected-svg");
saveAsPng.saveSvgAsPng(svg, "discotools-xyz-icon.png", {
scale: 1.25,
encoderOptions: 1,
});
// API.download();
};
const previewAvatar = () => {
if (user?.id) {
if (user?.avatar)
return `https://cdn.discordapp.com/avatars/${user?.id}/${user?.avatar}.png`;
else
return `https://cdn.discordapp.com/embed/avatars/${
user.discriminator % 5
}.png`;
}
return DefaultAvatar.src;
};
const renderColor = () => {
if (editor?.shape?.gradient?.enabled) {
const color = editor?.shape?.gradient?.colours?.[0]?.value;
if (color.includes("rgba")) {
const rgba = color?.split(",");
return `rgb(${rgba[0].split("(")[1]}, ${rgba[1]}, ${rgba[2]})`;
}
return color;
}
if (editor?.shape?.colour?.includes("rgba")) {
const rgba = editor?.shape?.colour?.split(",");
return `rgb(${rgba[0].split("(")[1]}, ${rgba[1]}, ${rgba[2]})`;
}
if (editor?.shape?.colour) {
return editor.shape.colour;
}
return "#fff";
};
return (
<div className="relative mt-20 max-w-6xl mx-auto z-1">
<ClydeMessage
message={intl.formatMessage({ id: "helper.title" })}
auto
onClick={() => setIsOpen(true)}
/>
<div
className="bg-dark-500 shadow-lg grid grid-cols-1 lg:grid-cols-5 rounded-2xl lg:max-h-[700px] lg:h-[700px]"
onClick={(e) => {
// e.preventDefault();
// e.stopPropagation();
}}
>
<div className="lg:col-span-3 flex flex-col justify-start overflow-hidden">
<EditorTabs current={currentTab} onChange={setCurrentTab} />
<div className="px-6 pb-6 pt-4 w-full overflow-y-auto h-full">
{renderTabs(currentTab)}
</div>
</div>
<div className="bg-dark-500 rounded-b-2xl lg:rounded-r-2xl col-span-2 flex flex-col flex-1 h-full">
<header
className="relative p-5 lg:p-8 flex items-center lg:rounded-tr-2xl justify-center bg-repeat h-[300px] w-full z-10 transition-all duration-200 first-step"
style={{
backgroundImage: `url(${BackgroundTransparent.src})`,
}}
>
<Icon
editor={editor}
id="discotools-selected-svg"
onChange={onChange}
onChangeTab={(i: number) => setCurrentTab(i)}
/>
</header>
<main className="lg:border-l border-dark-300 flex flex-1 flex-col px-5 py-6 justify-between gap-6">
<div>
<div className="grid grid-cols-1 gap-5">
<div className="flex items-start gap-3 justify-start">
<img
src={previewAvatar()}
width={32}
height={32}
alt="Default Avatar for user"
className="rounded-full object-cover w-10 h-10"
/>
<div className="text-left">
<div className="flex items-center justify-start gap-1">
<p
className="font-semibold text-base"
style={{ color: renderColor() }}
>
Captain Astro
</p>
<Icon size={24} editor={editor} />
<p className="text-white text-opacity-50 text-[10px]">
Today at 11:23 pm
</p>
</div>
<p className="text-white text-opacity-60 text-sm mt-0.5">
<FormattedMessage id="iconsEdtior.editor.preview.text1" />
</p>
</div>
</div>
<div className="flex items-start gap-3 justify-start">
<Image
src={DefaultAvatar2}
width={32}
height={32}
alt="Second user without custom roles icons"
className="rounded-full object-cover w-10 h-10"
/>
<div className="text-left">
<div className="flex items-center justify-start gap-1">
<p className="font-semibold text-base text-white">
Rookie
</p>
<p className="text-white text-opacity-50 text-[10px] ml-1">
Today at 11:23 pm
</p>
</div>
<p className="text-white text-opacity-60 text-sm mt-0.5">
<FormattedMessage
id="iconsEdtior.editor.preview.text2"
values={{
user: (t) => user?.username ?? "Captain Astro",
}}
/>
</p>
</div>
</div>
</div>
</div>
<button
className="text-white font-medium bg-blue hover:bg-blue tracking-wide text-base px-5 py-2.5 rounded justify-center flex items-center gap-2"
onClick={handleSaveIcon}
>
<FontAwesomeIcon icon={faDownload} className="w-4" />
<FormattedMessage id="iconsEdtior.editor.preview.download" />
</button>
</main>
</div>
</div>
</div>
);
}