feat: ui fixes

This commit is contained in:
neoapps-dev 2026-06-09 12:08:01 +03:00
parent eecd6dc506
commit cfcdb74606
2 changed files with 144 additions and 109 deletions

View file

@ -63,7 +63,10 @@ const CreditsView = memo(function CreditsView() {
{
role: "",
members: [
{ name: "Santiago Fisela", url: "https://github.com/PinkLittleKitty" },
{
name: "Santiago Fisela",
url: "https://github.com/PinkLittleKitty",
},
{ name: "Leon", url: "https://github.com/hornyalcoholic" },
{ name: "Criador_Mods", url: "https://github.com/CriadorMods" },
],
@ -81,9 +84,7 @@ const CreditsView = memo(function CreditsView() {
roles: [
{
role: "Founder",
members: [
{ name: "Piebot", url: "https://github.com/Piebot" },
],
members: [{ name: "Piebot", url: "https://github.com/Piebot" }],
},
],
subprojects: [
@ -94,7 +95,10 @@ const CreditsView = memo(function CreditsView() {
role: "Active Maintainer",
members: [
{ name: "Andi_pog", url: "https://github.com/Andi-pog" },
{ name: "LordCambion", url: "https://github.com/LordCambion" },
{
name: "LordCambion",
url: "https://github.com/LordCambion",
},
{ name: "neoapps", url: "https://github.com/neoapps-dev" },
{ name: "tranqlmao", url: "https://github.com/tranqlmao" },
],
@ -161,9 +165,7 @@ const CreditsView = memo(function CreditsView() {
roles: [
{
role: "Founder",
members: [
{ name: "Revela", url: "https://github.com/Revela" },
],
members: [{ name: "Revela", url: "https://github.com/Revela" }],
},
],
},
@ -173,9 +175,7 @@ const CreditsView = memo(function CreditsView() {
roles: [
{
role: "Founder",
members: [
{ name: "TBD", url: "#" },
],
members: [{ name: "TBD", url: "#" }],
},
],
},
@ -207,9 +207,7 @@ const CreditsView = memo(function CreditsView() {
roles: [
{
role: "",
members: [
{ name: "faisal508508", url: "#" },
],
members: [{ name: "faisal508508", url: "#" }],
},
],
},
@ -240,7 +238,9 @@ const CreditsView = memo(function CreditsView() {
onMouseLeave={() => setIsHovered(false)}
className="fixed bottom-8 left-8 z-50 h-10 flex items-center justify-center gap-2 px-4 text-xl mc-text-shadow outline-none border-none"
style={{
backgroundImage: isHovered ? "url('/images/button_highlighted.png')" : "url('/images/Button_Background.png')",
backgroundImage: isHovered
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
color: isHovered ? "#FFFF55" : "white",
@ -253,17 +253,26 @@ const CreditsView = memo(function CreditsView() {
initial={{ y: "50%" }}
animate={{ y: "-200%" }}
transition={{ duration: 45, ease: "linear" }}
onAnimationComplete={() => setActiveView("main")}
className="flex flex-col items-center justify-center space-y-8 py-20"
>
<div className="mb-8">
<img
src="/images/emerald_launcher.png"
alt="Emerald Launcher"
className="h-20"
style={{ imageRendering: "pixelated" }}
/>
</div>
{credits.map((cat) => (
<div key={cat.category} className="flex flex-col items-center gap-6">
<h2
<h2
className={`text-3xl font-bold mc-text-shadow uppercase tracking-wider text-center flex items-center gap-3 ${
cat.category === "LCE TEAM" ? "text-[#9B59B6]" :
cat.category === "SPECIAL THANKS" ? "text-[#FFD700]" :
"text-[#50C878]"
}`}
cat.category === "LCE TEAM"
? "text-[#9B59B6]"
: cat.category === "SPECIAL THANKS"
? "text-[#FFD700]"
: "text-[#50C878]"
}`}
style={{ textShadow: "2px 2px 0px #000000" }}
>
{cat.icon && (
@ -278,10 +287,17 @@ const CreditsView = memo(function CreditsView() {
</h2>
<div className="flex flex-col items-center gap-4">
{cat.subcategories.map((sub) => (
<div key={sub.name} className="flex flex-col items-center gap-3">
<h3 className={`text-2xl mc-text-shadow uppercase tracking-wide text-center flex items-center gap-3 ${
sub.name === "Discord Booster" ? "text-[#FF69B4]" : "text-white/90"
}`}>
<div
key={sub.name}
className="flex flex-col items-center gap-3"
>
<h3
className={`text-2xl mc-text-shadow uppercase tracking-wide text-center flex items-center gap-3 ${
sub.name === "Discord Booster"
? "text-[#FF69B4]"
: "text-white/90"
}`}
>
{sub.icon && (
<img
src={sub.icon}
@ -294,7 +310,10 @@ const CreditsView = memo(function CreditsView() {
</h3>
<div className="flex flex-col items-center gap-2">
{sub.roles.map((role) => (
<div key={role.role} className="flex flex-col items-center gap-2">
<div
key={role.role}
className="flex flex-col items-center gap-2"
>
{role.role && (
<h4 className="text-white/70 text-lg mc-text-shadow uppercase tracking-wide text-center">
{role.role}
@ -319,12 +338,18 @@ const CreditsView = memo(function CreditsView() {
{sub.subprojects && sub.subprojects.length > 0 && (
<div className="flex flex-col items-center gap-3 mt-4">
{sub.subprojects.map((project) => (
<div key={project.name} className="flex flex-col items-center gap-2">
<div
key={project.name}
className="flex flex-col items-center gap-2"
>
<h4 className="text-white/60 text-lg mc-text-shadow uppercase tracking-wide text-center">
{project.name}
</h4>
{project.roles.map((role) => (
<div key={role.role} className="flex flex-col items-center gap-2">
<div
key={role.role}
className="flex flex-col items-center gap-2"
>
{role.role && (
<h5 className="text-white/50 text-base mc-text-shadow uppercase tracking-wide text-center">
{role.role}
@ -338,7 +363,9 @@ const CreditsView = memo(function CreditsView() {
target="_blank"
rel="noopener noreferrer"
className="text-[#e2cc4c] text-xl mc-text-shadow font-medium cursor-pointer"
style={{ textShadow: "2px 2px 0px #000000" }}
style={{
textShadow: "2px 2px 0px #000000",
}}
>
{member.name}
</a>
@ -368,8 +395,8 @@ const CreditsView = memo(function CreditsView() {
</div>
<div className="bg-white rounded-xl p-3 shadow-2xl w-64">
<img
src="/images/esrb_warning.png"
alt="ESRB Warning"
src="/images/emerald_block.png"
alt="Emerald"
className="w-full h-auto object-contain"
style={{ imageRendering: "pixelated" }}
/>
@ -378,7 +405,9 @@ const CreditsView = memo(function CreditsView() {
<div className="flex flex-col items-center gap-2 mt-8">
<p className="text-white/60 text-sm mc-text-shadow text-center uppercase tracking-wider">
Minecraft is a trademark of Mojang Synergies AB. This project is not affiliated with, endorsed by, sponsored by, or specifically approved by Mojang, Microsoft, or 4J Studios.
Minecraft is a trademark of Mojang Synergies AB. This project is not
affiliated with, endorsed by, sponsored by, or specifically approved
by Mojang, Microsoft, or 4J Studios.
</p>
</div>
</motion.div>

View file

@ -1,4 +1,4 @@
import {
import React, {
useState,
useEffect,
memo,
@ -37,7 +37,7 @@ const SERVERS_BASE =
"https://raw.githubusercontent.com/bytebukkit/servers/refs/heads/main";
const CATEGORY_TABS = ["Skin", "Texture", "World", "Mod", "DLC"] as const;
const UTILITY_TABS = ["Versions", "Installed", "Search"] as const;
const SERVER_TABS = ["Server", "Plugins"] as const;
const SERVER_TABS = ["Server", "Server Plugins"] as const;
const ALL_TABS = [...CATEGORY_TABS, ...UTILITY_TABS, ...SERVER_TABS] as const;
type TabType = (typeof ALL_TABS)[number];
interface RegistryPackage {
@ -236,7 +236,7 @@ const WorkshopView = memo(function WorkshopView() {
}
return [];
}
if (activeTab === "Plugins" || activeTab === "Server") return [];
if (activeTab === "Server Plugins" || activeTab === "Server") return [];
return installedPkgs.filter((p) => p.packageId === pkgId);
},
[installedPkgs, activeTab, config.customEditions, versionPackages],
@ -244,7 +244,7 @@ const WorkshopView = memo(function WorkshopView() {
const isInstalled = useCallback(
(pkgId: string) => {
if (activeTab === "Plugins" || activeTab === "Server") return false;
if (activeTab === "Server Plugins" || activeTab === "Server") return false;
if (activeTab === "Versions") {
return (
config.customEditions?.some(
@ -263,7 +263,7 @@ const WorkshopView = memo(function WorkshopView() {
(pkg: RegistryPackage) => {
if (
activeTab === "Versions" ||
activeTab === "Plugins" ||
activeTab === "Server Plugins" ||
activeTab === "Server"
)
return false;
@ -288,7 +288,7 @@ const WorkshopView = memo(function WorkshopView() {
);
})
: installedPackageList
: activeTab === "Plugins"
: activeTab === "Server Plugins"
? search.trim()
? serverPlugins.filter((pkg) => {
if (
@ -485,7 +485,7 @@ const WorkshopView = memo(function WorkshopView() {
isSearchTab ||
isInstalledTab ||
isVersionTab ||
activeTab === "Plugins" ||
activeTab === "Server Plugins" ||
activeTab === "Server";
return (
<motion.div
@ -501,72 +501,78 @@ const WorkshopView = memo(function WorkshopView() {
Workshop
</h2>
<div className="flex items-center justify-center gap-2 mb-4 w-full flex-wrap px-4">
{CATEGORY_TABS.map((tab) => {
const isActive = tab === activeTab;
return (
<button
key={tab}
onClick={() => selectTab(tab)}
className={`
relative h-10 px-5 text-sm mc-text-shadow tracking-widest border-none outline-none cursor-pointer
${isActive ? "text-[#FFFF55]" : "text-white hover:text-[#FFFF55]"}
`}
style={{
backgroundImage: isActive
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
>
{tab.toUpperCase()}
</button>
);
})}
</div>
<div className="flex items-center justify-center gap-0 mb-4 w-full px-4">
<div className="flex items-center gap-1 px-[11px] py-1 rounded-sm bg-[#696969] border-2 border-black" style={{boxShadow: "inset 0 0 0 2px #fff"}}>
{CATEGORY_TABS.map((tab, i) => {
const isActive = tab === activeTab;
return (
<React.Fragment key={tab}>
{i > 0 && <div className="w-[2px] h-5 bg-[#777] shrink-0" />}
<button
onClick={() => selectTab(tab)}
className={`relative h-8 px-3 text-xs mc-text-shadow tracking-widest border-none outline-none cursor-pointer transition-colors rounded-sm ${
isActive
? "text-[#FFFF55] bg-[#FFFF55]/10 shadow-[0_0_12px_rgba(255,255,85,0.15)]"
: "text-[#aaa] hover:text-white hover:bg-white/5"
}`}
>
{tab.toUpperCase()}
</button>
</React.Fragment>
);
})}
</div>
<div className="flex items-center justify-center gap-2 mb-4 w-full flex-wrap px-4">
{SERVER_TABS.map((tab) => {
const isActive = tab === activeTab;
return (
<button
key={tab}
onClick={() => selectTab(tab)}
className={`
relative h-8 px-4 text-xs mc-text-shadow tracking-widest border outline-none cursor-pointer transition-all
${isActive ? "text-[#FFFF55] border-[#FFFF55] bg-black/40" : "text-[#A0A0A0] border-[#444] hover:text-white hover:border-[#888]"}
`}
>
{tab.toUpperCase()}
</button>
);
})}
<div className="w-px h-6 bg-[#444] mx-2" />
{UTILITY_TABS.map((tab) => {
const isActive = tab === activeTab;
const updateCount =
tab === "Installed"
? allPackages.filter((p) => hasUpdate(p)).length
: 0;
return (
<button
key={tab}
onClick={() => selectTab(tab)}
className={`
relative h-8 px-4 text-xs mc-text-shadow tracking-widest border outline-none cursor-pointer transition-all
${isActive ? "text-[#FFFF55] border-[#FFFF55] bg-black/40" : "text-[#A0A0A0] border-[#444] hover:text-white hover:border-[#888]"}
`}
>
{tab.toUpperCase()}
{updateCount > 0 && (
<span className="absolute -top-1.5 -right-1.5 bg-[#FF5555] text-white text-[8px] rounded-full w-4 h-4 flex items-center justify-center font-bold mc-text-shadow border border-[#AA0000]">
{updateCount}
</span>
)}
</button>
);
})}
<div className="flex items-center gap-1 px-[11px] py-1 ml-3 rounded-sm bg-[#696969] border-2 border-black" style={{boxShadow: "inset 0 0 0 2px #fff"}}>
{UTILITY_TABS.map((tab, i) => {
const isActive = tab === activeTab;
const updateCount =
tab === "Installed"
? allPackages.filter((p) => hasUpdate(p)).length
: 0;
return (
<React.Fragment key={tab}>
{i > 0 && <div className="w-[2px] h-5 bg-[#777] shrink-0" />}
<button
onClick={() => selectTab(tab)}
className={`relative h-8 px-3 text-xs mc-text-shadow tracking-widest border-none outline-none cursor-pointer transition-colors rounded-sm ${
isActive
? "text-[#FFFF55] bg-[#FFFF55]/10 shadow-[0_0_12px_rgba(255,255,85,0.15)]"
: "text-[#aaa] hover:text-white hover:bg-white/5"
}`}
>
{tab.toUpperCase()}
{updateCount > 0 && (
<span className="absolute -top-1.5 -right-1.5 bg-[#FF5555] text-white text-[8px] rounded-full w-4 h-4 flex items-center justify-center font-bold mc-text-shadow border border-[#AA0000]">
{updateCount}
</span>
)}
</button>
</React.Fragment>
);
})}
</div>
<div className="flex items-center gap-1 px-[11px] py-1 ml-3 rounded-sm bg-[#696969] border-2 border-black" style={{boxShadow: "inset 0 0 0 2px #fff"}}>
{SERVER_TABS.map((tab, i) => {
const isActive = tab === activeTab;
return (
<React.Fragment key={tab}>
{i > 0 && <div className="w-[2px] h-5 bg-[#777] shrink-0" />}
<button
onClick={() => selectTab(tab)}
className={`relative h-8 px-3 text-xs mc-text-shadow tracking-widest border-none outline-none cursor-pointer transition-colors rounded-sm ${
isActive
? "text-[#FFFF55] bg-[#FFFF55]/10 shadow-[0_0_12px_rgba(255,255,85,0.15)]"
: "text-[#aaa] hover:text-white hover:bg-white/5"
}`}
>
{tab.toUpperCase()}
</button>
</React.Fragment>
);
})}
</div>
</div>
<div className="w-[98%] flex-1 relative overflow-hidden mc-options-bg">
@ -594,7 +600,7 @@ const WorkshopView = memo(function WorkshopView() {
? "FILTER INSTALLED..."
: isVersionTab
? "FILTER VERSIONS..."
: activeTab === "Plugins"
: activeTab === "Server Plugins"
? "FILTER PLUGINS..."
: activeTab === "Server"
? "FILTER SERVERS..."
@ -617,7 +623,7 @@ const WorkshopView = memo(function WorkshopView() {
)}
</div>
</div>
{activeTab === "Plugins" && serverCategories.length > 1 && (
{activeTab === "Server Plugins" && serverCategories.length > 1 && (
<div className="flex items-center gap-2 px-6 pb-3 overflow-x-auto scroll-smooth">
{serverCategories.map((cat) => (
<button
@ -727,7 +733,7 @@ const WorkshopView = memo(function WorkshopView() {
<span className="text-2xl text-[#E0E0E0] mc-text-shadow uppercase tracking-widest opacity-60">
{isInstalledTab
? "Nothing Installed"
: activeTab === "Plugins"
: activeTab === "Server Plugins"
? "No plugins available"
: activeTab === "Server"
? "No servers available"
@ -754,7 +760,7 @@ const WorkshopView = memo(function WorkshopView() {
))}
</div>
)}
{(activeTab === "Plugins" || activeTab === "Server") && (
{(activeTab === "Server Plugins" || activeTab === "Server") && (
<div className="flex justify-center pt-4 pb-2">
<img
src="/images/bytebukkit.png"
@ -847,7 +853,7 @@ const WorkshopView = memo(function WorkshopView() {
onInstallComplete={refreshInstalled}
onUninstallComplete={refreshInstalled}
isVersionTab={activeTab === "Versions"}
isServerTab={activeTab === "Plugins"}
isServerTab={activeTab === "Server Plugins"}
isGameServerTab={activeTab === "Server"}
isSaved={
selectedPkg.server_address