Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	| 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={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={() => { | |
| 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> | |
| ); | |
| } | |
