From d49622495f5605c7aebccb335a58c05690c1e4e4 Mon Sep 17 00:00:00 2001 From: neoapps-dev Date: Thu, 13 Aug 2026 03:34:25 +0300 Subject: [PATCH] feat: builtin capes --- public/Capes/4J.png | Bin 0 -> 3555 bytes public/Capes/Unused_Cape_2.png | Bin 0 -> 730 bytes src/components/views/SkinsView.tsx | 52 +++++++++++++++++++++-------- 3 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 public/Capes/4J.png create mode 100644 public/Capes/Unused_Cape_2.png diff --git a/public/Capes/4J.png b/public/Capes/4J.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d4883a95c27153a9a0e405c0817903d539ef7d GIT binary patch literal 3555 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 literal 0 HcmV?d00001 diff --git a/public/Capes/Unused_Cape_2.png b/public/Capes/Unused_Cape_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a256f03ff39ab25f6cb97c1dad0fa091b0199372 GIT binary patch literal 730 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=%;U|?G4>EalY(U_DHQkIwyQ26)! zhhJ>WhmRlUiD2BX!`!?A$oY8k#?y<8?DmiUhlh6tTTf_cY-9u)@c(~OVnV_X{C6c#`mno<~@7^aA}DI<(#Iq;i(N;Ur!-Zm+?pwn5VfD4=6 zihZ0Xx2RH{M?yjZs-1;l#e-(G&uuTKE4~Gp8t1CY#%5Z`);76##bhrwX@m*7%nRhy zIodLcjx+G^@IbUX0kzL^W_obrxMDj~TTz06fdN!v3S*XDf`5IQf{|zfv-4UXxH&+d zFUjIleYWw#!vu>IW`sx58Ry8cGA5mFTgV1?p3@gr4#uP_4F>|eB;l4y-JAgnoWaXv YW?0nitPmTwAsrMTp00i_>zopr0CxWjE&u=k literal 0 HcmV?d00001 diff --git a/src/components/views/SkinsView.tsx b/src/components/views/SkinsView.tsx index bae0fbc..e6ee247 100644 --- a/src/components/views/SkinsView.tsx +++ b/src/components/views/SkinsView.tsx @@ -76,10 +76,15 @@ const DEFAULT_SKINS: SavedSkin[] = [ id: "tranqlmao", name: "Tranq", url: "/Skins/tranq.png", - isSlim: false, + isSlim: true, }, ]; +const DEFAULT_CAPES: SavedCape[] = [ + { id: "4j", name: "4J Studios", url: "/Capes/4J.png" }, + { id: "unused2", name: "Unused Cape 2", url: "/Capes/Unused_Cape_2.png" }, +]; + const HeadPreview = memo(function HeadPreview({ src }: { src: string }) { const canvasRef = useRef(null); @@ -135,13 +140,17 @@ const SkinsView = memo(function SkinsView() { "lce-custom-capes", [], ); + const savedCapes = [ + ...DEFAULT_CAPES, + ...storedCapes.filter((c) => !DEFAULT_CAPES.some((d) => d.id === c.id)), + ]; const [activeCapeId, setActiveCapeId] = useState(null); const TOP_BUTTONS_COUNT = viewMode === "skin" ? 3 : 3; const SKINS_START_INDEX = TOP_BUTTONS_COUNT; const BACK_BUTTON_INDEX = SKINS_START_INDEX + - (viewMode === "skin" ? savedSkins.length : storedCapes.length); + (viewMode === "skin" ? savedSkins.length : savedCapes.length); const ITEM_COUNT = BACK_BUTTON_INDEX + 1; const setSavedSkins = ( @@ -243,10 +252,10 @@ const SkinsView = memo(function SkinsView() { useEffect(() => { if (!activeCapeId) { - const match = storedCapes.find((c) => c.url === capeUrl); + const match = savedCapes.find((c) => c.url === capeUrl); if (match) setActiveCapeId(match.id); } - }, [activeCapeId, storedCapes, capeUrl]); + }, [activeCapeId, savedCapes, capeUrl]); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { @@ -333,7 +342,7 @@ const SkinsView = memo(function SkinsView() { setFocusIndex(0); } else if (focusIndex === BACK_BUTTON_INDEX) { const itemCount = - viewMode === "cape" ? storedCapes.length + 1 : savedSkins.length; + viewMode === "cape" ? savedCapes.length + 1 : savedSkins.length; setFocusIndex(SKINS_START_INDEX + itemCount - 1); } else if (focusIndex >= SKINS_START_INDEX) { const rowCount = 4; @@ -351,7 +360,18 @@ const SkinsView = memo(function SkinsView() { playPressSound(); setViewMode(viewMode === "skin" ? "cape" : "skin"); } else if (focusIndex < BACK_BUTTON_INDEX) { - handleSkinSelect(savedSkins[focusIndex - SKINS_START_INDEX]); + if (viewMode === "cape") { + const capeIdx = focusIndex - SKINS_START_INDEX; + if (capeIdx === 0) { + playPressSound(); + setCapeUrl(null); + setActiveCapeId(null); + } else { + handleCapeSelect(savedCapes[capeIdx - 1]); + } + } else { + handleSkinSelect(savedSkins[focusIndex - SKINS_START_INDEX]); + } } else { playBackSound(); setActiveView("main"); @@ -363,7 +383,7 @@ const SkinsView = memo(function SkinsView() { }, [ focusIndex, savedSkins.length, - storedCapes.length, + savedCapes.length, playBackSound, setActiveView, playPressSound, @@ -414,6 +434,9 @@ const SkinsView = memo(function SkinsView() { const isDefaultSkin = (id: string | null) => DEFAULT_SKINS.some((d) => d.id === id); + const isDefaultCape = (id: string | null) => + DEFAULT_CAPES.some((d) => d.id === id); + const handleDeleteActive = () => { if (!activeSkinId || isDefaultSkin(activeSkinId)) return; playPressSound(); @@ -457,7 +480,7 @@ const SkinsView = memo(function SkinsView() { }; const handleDeleteActiveCape = () => { - if (!activeCapeId) return; + if (!activeCapeId || isDefaultCape(activeCapeId)) return; playPressSound(); const updatedCapes = storedCapes.filter((c) => c.id !== activeCapeId); setStoredCapes(updatedCapes); @@ -476,6 +499,8 @@ const SkinsView = memo(function SkinsView() { isDefaultSkin(activeSkinId) || (!activeSkinId && skinUrl === "/images/Default.png"); const isActiveCapeDefault = !activeCapeId && !capeUrl; + const isCapeDeleteDisabled = + isActiveCapeDefault || isDefaultCape(activeCapeId); return ( { if (viewMode === "skin" && !isActiveDefault) setFocusIndex(1); - else if (viewMode === "cape" && !isActiveCapeDefault) + else if (viewMode === "cape" && !isCapeDeleteDisabled) setFocusIndex(1); }} onClick={() => { @@ -528,7 +553,7 @@ const SkinsView = memo(function SkinsView() { }} className={`w-40 h-10 flex items-center justify-center transition-colors text-2xl mc-text-shadow outline-none border-none ${ (viewMode === "skin" && isActiveDefault) || - (viewMode === "cape" && isActiveCapeDefault) + (viewMode === "cape" && isCapeDeleteDisabled) ? "text-gray-400 opacity-80 cursor-not-allowed" : focusIndex === 1 ? "text-[#FFFF55]" @@ -537,7 +562,7 @@ const SkinsView = memo(function SkinsView() { style={{ backgroundImage: (viewMode === "skin" && isActiveDefault) || - (viewMode === "cape" && isActiveCapeDefault) + (viewMode === "cape" && isCapeDeleteDisabled) ? "url('/images/Button_Background2.png')" : focusIndex === 1 ? "url('/images/button_highlighted.png')" @@ -673,7 +698,7 @@ const SkinsView = memo(function SkinsView() { No Cape - {storedCapes.map((cape, i) => { + {savedCapes.map((cape, i) => { const idx = SKINS_START_INDEX + 1 + i; const isActive = activeCapeId ? activeCapeId === cape.id @@ -707,9 +732,10 @@ const SkinsView = memo(function SkinsView() { onChange={(e) => handleCapeNameChange(cape.id, e.target.value) } - className={`bg-transparent text-center outline-none border-none text-base mc-text-shadow w-full truncate transition-colors relative z-10 ${isActive || isFocused ? "text-[#FFFF55]" : "text-white"}`} + className={`bg-transparent text-center outline-none border-none text-base mc-text-shadow w-full truncate transition-colors relative z-10 ${isActive || isFocused ? "text-[#FFFF55]" : "text-white"} ${isDefaultCape(cape.id) ? "pointer-events-none" : ""}`} onClick={(e) => e.stopPropagation()} spellCheck={false} + readOnly={isDefaultCape(cape.id)} /> );