mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-07-18 00:07:09 +00:00
feat: ui fixes
This commit is contained in:
parent
eecd6dc506
commit
cfcdb74606
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue