feat: skin viewer in skin changing menu

This commit is contained in:
neoapps-dev 2026-06-14 21:11:38 +03:00
parent ffd4e22d4a
commit 1b0150b719
3 changed files with 56 additions and 39 deletions

View file

@ -15,9 +15,10 @@ interface SkinViewerProps {
setActiveView: (view: string) => void;
isFocusedSection: boolean;
onNavigateRight: () => void;
hideControls?: boolean;
}
const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSound, skinUrl, capeUrl, setActiveView, isFocusedSection, onNavigateRight }: SkinViewerProps) {
const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSound, skinUrl, capeUrl, setActiveView, isFocusedSection, onNavigateRight, hideControls }: SkinViewerProps) {
const mountRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [focusIndex, setFocusIndex] = useState(0);
@ -263,7 +264,7 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSo
transition={{ duration: useConfig().animationsEnabled ? 0.3 : 0 }}
className={`absolute ${legacyMode ? 'left-[calc(50vw-340px)]' : 'left-16'} ${legacyMode ? 'top-1/2' : 'top-[40%]'} -translate-y-1/2 flex flex-col items-center gap-1 outline-none z-10`}
>
{!legacyMode && (
{!hideControls && !legacyMode && (
<div className={`relative z-20 bg-black/20 flex justify-center items-center ${legacyMode ? 'mb-0' : 'mb-2'} px-2 py-1 rounded-sm border-2 transition-colors ${isFocusedSection && focusIndex === 0 ? 'border-[#FFFF55]' : 'border-transparent'}`} data-focus="0" tabIndex={0}>
<input
type="text" value={username} maxLength={16}
@ -284,38 +285,40 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSo
<div ref={mountRef} className="absolute drop-shadow-[0_8px_8px_rgba(0,0,0,0.8)] cursor-ew-resize outline-none w-[260px] h-[450px] -translate-y-6" />
</div>
)}
<div className={`flex ${legacyMode ? 'flex-col gap-2 mt-0' : 'flex-row gap-4 mt-2'} items-center`}>
<button
data-focus="1" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(1)}
onClick={() => { playPressSound(); setActiveView('skins'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 1 ? '' : ''}`}
style={isFocusedSection && focusIndex === 1 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="Change Skin"
>
<img src="/images/Change_Skin_Icon.png" alt="Skin" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
<button
data-focus="2" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(2)}
onClick={() => { playPressSound(); setActiveView('screenshots'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 2 ? '' : ''}`}
style={isFocusedSection && focusIndex === 2 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="Screenshots"
>
<img src="/images/Screenshots_Icon.png" alt="Screenshots" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
<button
data-focus="3" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(3)}
onClick={() => { playPressSound(); setActiveView('lcelive'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 3 ? '' : ''}`}
style={isFocusedSection && focusIndex === 3 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="LCELive"
>
<img src="/images/friends.png" alt="LCELive" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
</div>
{!hideControls && (
<div className={`flex ${legacyMode ? 'flex-col gap-2 mt-0' : 'flex-row gap-4 mt-2'} items-center`}>
<button
data-focus="1" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(1)}
onClick={() => { playPressSound(); setActiveView('skins'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 1 ? '' : ''}`}
style={isFocusedSection && focusIndex === 1 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="Change Skin"
>
<img src="/images/Change_Skin_Icon.png" alt="Skin" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
<button
data-focus="2" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(2)}
onClick={() => { playPressSound(); setActiveView('screenshots'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 2 ? '' : ''}`}
style={isFocusedSection && focusIndex === 2 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="Screenshots"
>
<img src="/images/Screenshots_Icon.png" alt="Screenshots" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
<button
data-focus="3" tabIndex={0}
onMouseEnter={() => isFocusedSection && setFocusIndex(3)}
onClick={() => { playPressSound(); setActiveView('lcelive'); }}
className={`mc-sq-btn w-12 h-12 flex items-center justify-center outline-none border-none ${isFocusedSection && focusIndex === 3 ? '' : ''}`}
style={isFocusedSection && focusIndex === 3 ? { backgroundImage: "url('/images/Button_Square_Highlighted.png')" } : {}}
title="LCELive"
>
<img src="/images/friends.png" alt="LCELive" className="w-8 h-8 object-contain" style={{ imageRendering: 'pixelated' }} />
</button>
</div>
)}
</motion.div>
);

View file

@ -861,7 +861,6 @@ const SettingsView = memo(function SettingsView() {
<div className="w-full space-y-3 flex flex-col items-center overflow-y-auto max-h-[50vh] py-2 settings-scrollbar">
{settingsItems.map((item, index) => {
if (item.id === "back") return null;
if (item.type === "slider") {
return (
<div

View file

@ -8,6 +8,7 @@ import {
useSkin,
useConfig,
} from "../../context/LauncherContext";
import SkinViewer from "../common/SkinViewer";
interface SavedSkin {
id: string;
@ -674,10 +675,9 @@ const SkinsView = memo(function SkinsView() {
className="absolute max-w-none"
style={{
width: "auto",
height: "200%",
left: "50%",
top: "-50%",
transform: "translateX(-50%)",
height: "100%",
left: "0",
top: "0",
imageRendering: "pixelated",
}}
loading="lazy"
@ -703,6 +703,21 @@ const SkinsView = memo(function SkinsView() {
</div>
</div>
<div className="w-full max-w-160 shadow-2xl flex flex-col items-center">
<SkinViewer
username=""
setUsername={() => {}}
playPressSound={playPressSound}
skinUrl={skinUrl}
setSkinUrl={setSkinUrl}
capeUrl={capeUrl}
setActiveView={setActiveView}
isFocusedSection={false}
onNavigateRight={() => {}}
hideControls
/>
</div>
<button
data-index={BACK_BUTTON_INDEX}
onMouseEnter={() => setFocusIndex(BACK_BUTTON_INDEX)}