diff --git a/public/images/background.png b/public/images/background.png new file mode 100644 index 0000000..341ffad Binary files /dev/null and b/public/images/background.png differ diff --git a/public/images/notification.png b/public/images/notification.png new file mode 100644 index 0000000..68a260b Binary files /dev/null and b/public/images/notification.png differ diff --git a/src/components/common/ClickParticles.tsx b/src/components/common/ClickParticles.tsx index 12c5052..3e0628b 100644 --- a/src/components/common/ClickParticles.tsx +++ b/src/components/common/ClickParticles.tsx @@ -16,7 +16,7 @@ export const ClickParticles: React.FC = React.memo(() => { const [bursts, setBursts] = useState([]); useEffect(() => { - const handleClick = (e: MouseEvent) => { + const handlePressSound = (e: MouseEvent) => { const newParticles: Particle[] = []; const particleCount = 8; @@ -38,8 +38,8 @@ export const ClickParticles: React.FC = React.memo(() => { }, 1000); }; - window.addEventListener("mousedown", handleClick); - return () => window.removeEventListener("mousedown", handleClick); + window.addEventListener("mousedown", handlePressSound); + return () => window.removeEventListener("mousedown", handlePressSound); }, []); return ( diff --git a/src/components/common/SkinViewer.tsx b/src/components/common/SkinViewer.tsx index 9282773..71c8235 100644 --- a/src/components/common/SkinViewer.tsx +++ b/src/components/common/SkinViewer.tsx @@ -7,7 +7,7 @@ import { useConfig } from '../../context/LauncherContext'; interface SkinViewerProps { username: string; setUsername: (name: string) => void; - playClickSound: () => void; + playPressSound: () => void; skinUrl: string; setSkinUrl: (url: string) => void; setActiveView: (view: string) => void; @@ -15,7 +15,7 @@ interface SkinViewerProps { onNavigateRight: () => void; } -const SkinViewer = memo(function SkinViewer({ username, setUsername, playClickSound, skinUrl, setSkinUrl, setActiveView, isFocusedSection, onNavigateRight }: SkinViewerProps) { +const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSound, skinUrl, setSkinUrl, setActiveView, isFocusedSection, onNavigateRight }: SkinViewerProps) { const mountRef = useRef(null); const containerRef = useRef(null); const [focusIndex, setFocusIndex] = useState(0); @@ -232,13 +232,13 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playClickSo if (focusIndex === 0) { (containerRef.current?.querySelector('input') as HTMLElement)?.focus(); } else if (focusIndex === 1) { - playClickSound(); + playPressSound(); setActiveView('skins'); } else if (focusIndex === 2) { - playClickSound(); + playPressSound(); setShowLayers(!showLayers); } else if (focusIndex === 3) { - playClickSound(); + playPressSound(); setSkinUrl('/images/Default.png'); } } @@ -246,7 +246,7 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playClickSo window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); - }, [isFocusedSection, focusIndex, onNavigateRight, playClickSound, setActiveView, setShowLayers, showLayers, setSkinUrl, legacyMode]); + }, [isFocusedSection, focusIndex, onNavigateRight, playPressSound, setActiveView, setShowLayers, showLayers, setSkinUrl, legacyMode]); useEffect(() => { if (isFocusedSection) { @@ -289,7 +289,7 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playClickSo ); - } + })} + + ) : ( + // Sub-menus - new style with background.png and toggle switches +
+
+ {settingsItems.map((item, index) => { + if (item.id === "back") return null; - const isRed = (item as any).color === "red"; - const isSmall = (item as any).small; + if (item.type === "slider") { + return ( +
setFocusIndex(index)} + className="relative w-[360px] h-10 flex items-center justify-center cursor-pointer transition-all outline-none border-none hover:text-[#FFFF55] shrink-0" + style={getSliderStyle(index)} + > + + {item.label} + +
+ item.onChange(parseInt(e.target.value))} + onMouseUp={playPressSound} + className="mc-slider-custom w-[calc(100%+16px)] h-full opacity-100 cursor-pointer z-20 outline-none m-0" + /> +
+
+ ); + } - return ( - - ); - })} -
+ const isRed = (item as any).color === "red"; + const isSmall = (item as any).small; + const isToggle = isToggleOption(item.label); + const toggleState = isToggle ? getToggleState(item.label) : false; + + return ( + + ); + })} +
+ + )} {(() => { const backIndex = settingsItems.findIndex((i) => i.id === "back"); @@ -557,9 +645,14 @@ const SettingsView = memo(function SettingsView() { data-index={backIndex} onMouseEnter={() => setFocusIndex(backIndex)} onClick={backItem.onClick} - className={`w-72 h-10 flex items-center justify-center transition-colors text-xl mc-text-shadow outline-none border-none hover:text-[#FFFF55] ${focusIndex === backIndex ? "text-[#FFFF55]" : "text-white" - }`} - style={getItemStyle(backIndex)} + className={`w-72 h-10 flex items-center justify-center transition-colors text-xl mc-text-shadow outline-none border-none hover:text-[#FFFF55] mt-4 ${focusIndex === backIndex ? "text-[#FFFF55]" : "text-white"}`} + style={{ + backgroundImage: focusIndex === backIndex + ? "url('/images/button_highlighted.png')" + : "url('/images/Button_Background.png')", + backgroundSize: "100% 100%", + imageRendering: "pixelated", + }} > Back diff --git a/src/components/views/SetupView.tsx b/src/components/views/SetupView.tsx index 8e3a201..7e5b19c 100644 --- a/src/components/views/SetupView.tsx +++ b/src/components/views/SetupView.tsx @@ -25,7 +25,7 @@ const SetupView: React.FC = ({ onComplete }) => { rpcEnabled: configRpc, keepLauncherOpen: configKeepOpen } = useConfig(); - const { playClickSound, playSfx } = useAudio(); + const { playPressSound, playSfx } = useAudio(); const { editions } = useGame(); const titleImage = editions.find(e => e.id === profile)?.titleImage || "/images/MenuTitle.png"; @@ -103,12 +103,12 @@ const SetupView: React.FC = ({ onComplete }) => { }; const handleRunnerSelect = (runnerId: string) => { - playClickSound(); + playPressSound(); setSelectedRunner(runnerId); }; const handleNext = async () => { - playClickSound(); + playPressSound(); if (currentStep === 0) { setUsername(tempUsername); @@ -136,7 +136,7 @@ const SetupView: React.FC = ({ onComplete }) => { }; const handleBack = () => { - playClickSound(); + playPressSound(); if (currentStep > 0) { setCurrentStep(currentStep - 1); setFocusIndex(0); @@ -180,10 +180,10 @@ const SetupView: React.FC = ({ onComplete }) => { else if (focusIndex === 1) handleNext(); } } else if (currentStep === 2) { - if (focusIndex === 0) { setEnableTrayIcon(!enableTrayIcon); playClickSound(); } - else if (focusIndex === 1) { setEnableVfx(!enableVfx); playClickSound(); } - else if (focusIndex === 2) { setEnableDiscordRPC(!enableDiscordRPC); playClickSound(); } - else if (focusIndex === 3) { setKeepLauncherOpen(!keepLauncherOpen); playClickSound(); } + if (focusIndex === 0) { setEnableTrayIcon(!enableTrayIcon); playPressSound(); } + else if (focusIndex === 1) { setEnableVfx(!enableVfx); playPressSound(); } + else if (focusIndex === 2) { setEnableDiscordRPC(!enableDiscordRPC); playPressSound(); } + else if (focusIndex === 3) { setKeepLauncherOpen(!keepLauncherOpen); playPressSound(); } else if (focusIndex === 4) handleBack(); else if (focusIndex === 5) handleNext(); } else if (currentStep === 3) { @@ -197,7 +197,7 @@ const SetupView: React.FC = ({ onComplete }) => { }, [currentStep, focusIndex, runners, enableTrayIcon, enableVfx, enableDiscordRPC, keepLauncherOpen, isLinux, isMac, tempUsername]); const handleMacosSetup = async () => { - playClickSound(); + playPressSound(); setIsSettingUpRuntime(true); setSetupProgress({ stage: "preparing", message: "Preparing macOS runtime setup...", percent: 0 }); @@ -444,7 +444,7 @@ const SetupView: React.FC = ({ onComplete }) => {