diff --git a/src/app/(main)/account/settings/layout.tsx b/src/app/(main)/account/settings/layout.tsx index c0ec24d..b1e73bf 100644 --- a/src/app/(main)/account/settings/layout.tsx +++ b/src/app/(main)/account/settings/layout.tsx @@ -40,7 +40,7 @@ export default function RootLayout({ const pathname = usePathname(); return ( - + {children} ); diff --git a/src/app/(main)/account/settings/page.tsx b/src/app/(main)/account/settings/page.tsx index 16402ae..8994353 100644 --- a/src/app/(main)/account/settings/page.tsx +++ b/src/app/(main)/account/settings/page.tsx @@ -85,7 +85,7 @@ export default function Settings() {
Unlink Account
-

Unlink your Minecraft acconut if you have already linked one.

+

Unlink your Minecraft account if you have already linked one.

{!linked && ( - - - - - - -
- - - -
- - - - - - - - -
- {children}{" "} -
- - ); + return ( + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + +
+ {children}{" "} +
+
+ ); } diff --git a/src/components/ServerCard.tsx b/src/components/ServerCard.tsx index 4b211b7..3994eb5 100644 --- a/src/components/ServerCard.tsx +++ b/src/components/ServerCard.tsx @@ -49,7 +49,13 @@ import { } from "./ui/card"; import { TooltipContent, TooltipTrigger } from "./ui/tooltip"; -export default function ServerCard({ b, motd, mini, favs }: any) { +export default function ServerCard({ + b, + motd, + mini, + favs, + selectedProperties, +}: any) { const router = useRouter(); const clipboard = useClipboard(); const [favoriteStar, setFavoriteStar] = useState(false); @@ -165,100 +171,110 @@ export default function ServerCard({ b, motd, mini, favs }: any) { - {b.author != undefined ? ( + + {selectedProperties.includes("Author") && + b.author != undefined ? (
by {b.author}
) : (
)} - + {selectedProperties.includes("Tags") && } - {b.playerData.playerCount == 0 ? ( -
- ) : ( -
+ {selectedProperties.includes("Players Online") && ( + <> + {b.playerData.playerCount == 0 ? ( +
+ ) : ( +
+ )} + )} - - {b.playerData.playerCount}{" "} - {b.playerData.playerCount == 1 ? "player" : "players"}{" "} - currently online {favs && <>• {favs} favorited} - + {selectedProperties.includes("Players Online") && ( + + {b.playerData.playerCount}{" "} + {b.playerData.playerCount == 1 ? "player" : "players"}{" "} + currently online {favs && <>• {favs} favorited} + + )} - - - <> - + + + + + + + + Open up the server page to see more information about + the server + + + + + + { clipboard.writeText(b.name + ".mshf.minehut.gg"); toast.success("Copied IP to clipboard"); }} > - - {b.name} - - - - - - - - - Open up the server page to see more information about - the server - - - - - - { - clipboard.writeText(b.name + ".mshf.minehut.gg"); - toast.success("Copied IP to clipboard"); - }} - > - Copy server IP -
- -
-
- - - Open server page - -
-
+ Copy server IP +
+ +
+ + + + Open server page + + + + )} - - {motd && ( + + {motd && selectedProperties.includes("MOTD") && ( , - className: "lg:row-start-1 lg:row-end-2 lg:col-start-2 lg:col-end-3", - }, - { - Icon: InputIcon, - name: "Descriptions", - href: "/docs/guides/customization", - cta: "Learn more", - description: - "Format your descriptions using Markdown to show what your server has to offer.", - background: , - className: "lg:col-start-1 lg:col-end-2 lg:row-start-1 lg:row-end-2", - }, - { - Icon: ImageIcon, - name: "Banners", - href: "/docs/guides/customization", - cta: "Learn more", - description: - "Show a banner with can contain images that show on your server page.", - background: , - className: "lg:col-start-3 lg:col-end-4 lg:row-start-1 lg:row-end-2", - }, + { + Icon: ChatBubbleIcon, + name: "Add a Discord widget", + description: + "Show where your players talk to each-other, including an online users count.", + href: "/docs/guides/customization", + cta: "Learn more", + background: , + className: "lg:row-start-1 lg:row-end-2 lg:col-start-2 lg:col-end-3", + }, + { + Icon: InputIcon, + name: "Descriptions", + href: "/docs/guides/customization", + cta: "Learn more", + description: + "Format your descriptions using Markdown to show what your server has to offer.", + background: , + className: "lg:col-start-1 lg:col-end-2 lg:row-start-1 lg:row-end-2", + }, + { + Icon: ImageIcon, + name: "Banners", + href: "/docs/guides/customization", + cta: "Learn more", + description: + "Show a banner with can contain images that show on your server page.", + background: , + className: "lg:col-start-3 lg:col-end-4 lg:row-start-1 lg:row-end-2", + }, ]; export default function ServerList() { - const [loading, setLoading]: any = useState(true); - const [randomText, setRandomText] = useState(""); - const [motdList, setMotdList] = useState({}); - const allText = [""]; - const getRandomText = () => { - return allText[Math.floor(Math.random() * allText.length)]; - }; - const [templateFilter, setTemplateFilter] = useState(false); - const [random, setRandom] = useState(false); - const [serverList, setServerList] = useState(new ServersList([])); - const [textCopied, setTextCopied] = useState(false); - const [padding, setPadding] = useState("0"); - const bigger = async (server: OnlineServer) => - server.playerData.playerCount > 15; - const smaller = async (server: OnlineServer) => - !server.staticInfo.alwaysOnline && - server.playerData.playerCount < 15 && - server.playerData.playerCount > 7; - const [nameFilters, setNameFilters] = useState({}); - const [inErrState, setErrState] = useState(false); - const [servers, setServers] = useState>([]); - const clipboard = useClipboard(); - const router = useRouter(); - const { user, isSignedIn } = useUser(); - const [pOS, setpOS] = useState(false); - const [ipr, setIPR] = useState("4"); - const [presentationMode, setPresentationMode] = useState<"table" | "grid">( - "grid", - ); - const [am, setAM] = useState(false); - const [filters, setFilters] = useState< - Array<(server: OnlineServer) => Promise> - >([]); - const [randomData, setRandomData] = useState( - undefined, - ); - const { resolvedTheme } = useTheme(); - const [color, setColor] = useState("#ffffff"); + const [loading, setLoading]: any = useState(true); + const [randomText, setRandomText] = useState(""); + const [motdList, setMotdList] = useState({}); + const allText = [""]; + const getRandomText = () => { + return allText[Math.floor(Math.random() * allText.length)]; + }; + const [templateFilter, setTemplateFilter] = useState(false); + const [random, setRandom] = useState(false); + const [serverList, setServerList] = useState(new ServersList([])); + const [textCopied, setTextCopied] = useState(false); + const [padding, setPadding] = useState("0"); + const bigger = async (server: OnlineServer) => + server.playerData.playerCount > 15; + const smaller = async (server: OnlineServer) => + !server.staticInfo.alwaysOnline && + server.playerData.playerCount < 15 && + server.playerData.playerCount > 7; + const [nameFilters, setNameFilters] = useState({}); + const [inErrState, setErrState] = useState(false); + const [servers, setServers] = useState>([]); + const clipboard = useClipboard(); + const router = useRouter(); + const { user, isSignedIn } = useUser(); + const [pOS, setpOS] = useState(false); + const [selectedProperties, setSelectedProperties] = useState([ + "Author", + "MOTD", + "Tags", + "Players Online", + "Actions", + ]); + const [ipr, setIPR] = useState("4"); + const [presentationMode, setPresentationMode] = useState<"table" | "grid">( + "grid" + ); + const [am, setAM] = useState(false); + const [filters, setFilters] = useState< + Array<(server: OnlineServer) => Promise> + >([]); + const [randomData, setRandomData] = useState( + undefined + ); + const { resolvedTheme } = useTheme(); + const [color, setColor] = useState("#ffffff"); - useEffect(() => { - setColor(resolvedTheme === "dark" ? "#ffffff" : "#000000"); - }, [resolvedTheme]); + useEffect(() => { + setColor(resolvedTheme === "dark" ? "#ffffff" : "#000000"); + }, [resolvedTheme]); - useEffect(() => { - if (isSignedIn) { - setAM(true); - console.log(user.publicMetadata); + useEffect(() => { + if (isSignedIn) { + setAM(true); + console.log(user.publicMetadata); - setIPR((user.publicMetadata.ipr as string | undefined) || "4"); - setPadding((user.publicMetadata.pad as string | undefined) || "0"); - setpOS((user.publicMetadata.srv as boolean | undefined) || false); - } - }, [isSignedIn, user]); + setIPR((user.publicMetadata.ipr as string | undefined) || "4"); + setPadding((user.publicMetadata.pad as string | undefined) || "0"); + setpOS((user.publicMetadata.srv as boolean | undefined) || false); + } + }, [isSignedIn, user]); - useEffectOnce(() => { - setRandomText(getRandomText()); - serverList - .fetchDataAndFilter() - .then(() => { - serverList.moveListDown(); - let stringList: Array<{ server: string; motd: string }> = []; - let obj: any = {}; + useEffectOnce(() => { + setRandomText(getRandomText()); + serverList + .fetchDataAndFilter() + .then(() => { + serverList.moveListDown(); + let stringList: Array<{ server: string; motd: string }> = []; + let obj: any = {}; - serverList.currentServers.forEach((b) => { - stringList.push({ motd: b.motd, server: b.name }); - }); + serverList.currentServers.forEach((b) => { + stringList.push({ motd: b.motd, server: b.name }); + }); - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach((b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }); - setMotdList(updatedSL); - setServers(serverList.currentServers); - setLoading(false); - }); - }) - .catch(() => setErrState(true)); - }); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + setLoading(false); + }); + }) + .catch(() => setErrState(true)); + }); - const ref = useRef(null); - const [clickedPage, setClickedPage] = useState("banners"); - const [hero, setHero] = useState(false); - if (inErrState) { - return ( - <> -
- -
-
-
- Hmm. Something is wrong. Reload the page. -
- - ); - } + const ref = useRef(null); + const [clickedPage, setClickedPage] = useState("banners"); + const [hero, setHero] = useState(false); + if (inErrState) { + return ( + <> +
+ +
+
+
+ Hmm. Something is wrong. Reload the page. +
+ + ); + } - if (loading) { - return ( -
- -
- - - -
-
- -
-
- - - - -
-
-
- ); - } + if (loading) { + return ( +
+ +
+ + + +
+
+ +
+
+ + + + +
+
+
+ ); + } - return ( -
-
- <> - {(!isSignedIn || hero) && ( -
- - - <> - Meet MHSF,
the modern - server finder - -
-

- MHSF is the next generation server list for Minehut, with - interactive filters,
{" "} - intuitive keyboard shortcuts, and everything between. -

+ return ( +
+
+ <> + {(!isSignedIn || hero) && ( +
+ + + <> + Meet MHSF,
the modern + server finder + +
+

+ MHSF is the next generation server list for Minehut, with + interactive filters,
{" "} + intuitive keyboard shortcuts, and everything between. +

- - - - - - - - - - - - - -
-
- + + + + + + + + + + + + + +
+
+ - Hero Image - Hero Image -
-
-
-
- - For players - -
-
-

- Find what you want now, not later -

-

- Use interactive filters and customization modes to find the - server of your choice -
in less than 10 minutes. -

-
- - {serverList.currentServers.slice(0, 20).map((server) => ( -
- router.push(pageFind(`Server:${server.name}`)) - } - > -
-
-
- - {server.name} -
- {server.author && ( -

- by {server.author} -

- )} -
-
-
- ))} -
- - {serverList.currentServers.slice(0, 20).map((server) => ( -
router.push(`/server/${server.name}`)} - > -
-
-
- - {server.name} -
- {server.author && ( -

- by {server.author} -

- )} -
-
-
- ))} -
-
+ Hero Image + Hero Image +
+
+
+
+ + For players + +
+
+

+ Find what you want now, not later +

+

+ Use interactive filters and customization modes to find the + server of your choice +
in less than 10 minutes. +

+
+ + {serverList.currentServers.slice(0, 20).map((server) => ( +
+ router.push(pageFind(`Server:${server.name}`)) + } + > +
+
+
+ + {server.name} +
+ {server.author && ( +

+ by {server.author} +

+ )} +
+
+
+ ))} +
+ + {serverList.currentServers.slice(0, 20).map((server) => ( +
router.push(`/server/${server.name}`)} + > +
+
+
+ + {server.name} +
+ {server.author && ( +

+ by {server.author} +

+ )} +
+
+
+ ))} +
+
-
-
-
- - For server owners - -
-
-

- Make your server stand out -

-

- Servers can have custom banners, Discord widgets, color schemes, - and descriptions, making your server stand out with information - that can be shown to players. -

- - {features.map((feature, idx) => ( - - ))} - - -
-
-

- Monitor your success -

-

- Ever wondered how a server was doing? MHSF constantly monitors servers - and shows you statistics about how a server is doing at any point of time. -

- -
- )} -
- -
-
- -
- - = 3200 - ? "bg-clip-text text-transparent bg-gradient-to-r from-cyan-500 to-blue-500" - : "" - } - > - Servers online{" "} -
- } - className="relative z-0" - desc={ -
-
= 3200 - ? "bg-clip-text text-transparent bg-gradient-to-r from-cyan-500 to-blue-500 " - : "" - } - > - {serverList.getExtraData().total_servers.toString()} -
- {serverList.getExtraData().total_servers >= 3200 && ( - - - - - - The server amount is over 3.2k, meaning that new servers - have to go into a queue before being able to be online.{" "} -
- (the server count isn't entirely accurate, so sometimes - you might not go into a queue even when the server count - is at 3.2k) -
-
- )} -
- } - icon={Network} - > - {serverList.getExtraData().total_servers >= 3200 && ( - - )} - - - {serverList.currentServers[0] != undefined - ? serverList.currentServers[0].name - : "None"}{" "} - {serverList.currentServers[0] != undefined && ( - - )} - - } - icon={Sun} - /> -
- -
- - - - - - Servers - - events.emit("search-request-event")} - > - Search Servers - - - +Shift+K - - - { - setRandomData(serverList.getRandomServer()); - setRandom(true); - }} - > - Pick Random Server - - - { - toast.promise( - new Promise((s, e) => { - setLoading(true); - serverList - .fetchDataAndFilter() - .then(() => { - serverList.moveListDown(); +
+
+
+ + For server owners + +
+
+

+ Make your server stand out +

+

+ Servers can have custom banners, Discord widgets, color schemes, + and descriptions, making your server stand out with information + that can be shown to players. +

+ + {features.map((feature, idx) => ( + + ))} + - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; +
+
+

+ Monitor your success +

+

+ Ever wondered how a server was doing? MHSF constantly monitors + servers and shows you statistics about how a server is doing at + any point of time. +

+ +
+ + Check it out below! + +
+ )} +
+ +
+
+ +
+ + = 3200 + ? "bg-clip-text text-transparent bg-gradient-to-r from-cyan-500 to-blue-500" + : "" + } + > + Servers online{" "} +
+ } + className="relative z-0" + desc={ +
+
= 3200 + ? "bg-clip-text text-transparent bg-gradient-to-r from-cyan-500 to-blue-500 " + : "" + } + > + {serverList.getExtraData().total_servers.toString()} +
+ {serverList.getExtraData().total_servers >= 3200 && ( + + + + + + The server amount is over 3.2k, meaning that new servers + have to go into a queue before being able to be online.{" "} +
+ (the server count isn't entirely accurate, so sometimes + you might not go into a queue even when the server count + is at 3.2k) +
+
+ )} +
+ } + icon={Network} + > + {serverList.getExtraData().total_servers >= 3200 && ( + + )} + + + {serverList.currentServers[0] != undefined + ? serverList.currentServers[0].name + : "None"}{" "} + {serverList.currentServers[0] != undefined && ( + + )} + + } + icon={Sun} + /> +
+ +
+ + + + { + if (am) + toast.warning( + "These settings will not change over reloads because you have account specific options enabled", + { + action: { + label: "Check settings", + onClick: () => + router.push("/account/settings/options"), + }, + } + ); + setPadding(v); + }, + am, + iprChangerCallback: (v: any) => { + if (am) + toast.warning( + "These settings will not change over reloads because you have account specific options enabled", + { + action: { + label: "Check settings", + onClick: () => + router.push("/account/settings/options"), + }, + } + ); + setIPR(v); + }, + ipr, + }} + pickRandomServerCallback={() => { + setRandomData(serverList.getRandomServer()); + setRandom(true); + }} + refreshCallback={() => { + toast.promise( + new Promise((s, e) => { + setLoading(true); + serverList + .fetchDataAndFilter() + .then(() => { + serverList.moveListDown(); - serverList.currentServers.forEach((b) => { - stringList.push({ - motd: b.motd, - server: b.name, - }); - }); + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach( - (b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }, - ); - setMotdList(updatedSL); - setServers(serverList.currentServers); - setLoading(false); - s(false); - }); - }) - .catch(() => { - e(); - }); - }), - { - success: "Succesfully refreshed servers", - loading: "Refreshing...", - error: "Error while refreshing", - }, - ); - }} - > - Refresh - - - - - Filter - - { - toast.promise( - new Promise((g, b) => { - if (v == "smaller") { - setTemplateFilter(true); - var filt = nameFilters; - filt["smaller-tf"] = true; - filt["bigger-tf"] = false; - setNameFilters(filt); + serverList.currentServers.forEach((b) => { + stringList.push({ + motd: b.motd, + server: b.name, + }); + }); - var filt2 = filters; - filt2.push(smaller); - if (filt2.includes(bigger)) { - filt2.splice(filt2.indexOf(bigger), 1); - } - setFilters(filt2); - serverList.editFilters(filters); - serverList.fetchDataAndFilter().then(() => { - serverList.moveListDown(); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + setLoading(false); + s(false); + }); + }) + .catch(() => { + e(); + }); + }), + { + success: "Succesfully reloaded servers", + loading: "Reloading...", + error: "Error while refreshing", + } + ); + }} + linksProps={{ + templateFilter, + tagChangerValueCallback: (tag: any) => { + return nameFilters["t-" + tag.docsName]; + }, + categoryChangerValueCallback: (categorie: any) => { + return nameFilters["c-" + categorie.name]; + }, + categoryChangerCallback: (categorie: any) => async (b: any) => { + var filt = nameFilters; + filt["c-" + categorie.name] = b; + setNameFilters(filt); + if (b) { + var filt2 = filters; + filt2.push(categorie.condition); + setFilters(filt2); + } else { + var filt2 = filters; + filt2.splice(filt2.indexOf(categorie.condition), 1); + setFilters(filt2); + } + serverList.editFilters(filters); + serverList.fetchDataAndFilter().then(() => { + serverList.moveListDown(); - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - serverList.currentServers.forEach((b) => { - stringList.push({ - motd: b.motd, - server: b.name, - }); - }); + serverList.currentServers.forEach((b) => { + stringList.push({ motd: b.motd, server: b.name }); + }); - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach( - (b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }, - ); - setMotdList(updatedSL); - setServers(serverList.currentServers); - g(undefined); - }); - }); - } else if (v == "bigger") { - setTemplateFilter(true); - var filt = nameFilters; - filt["smaller-tf"] = false; - filt["bigger-tf"] = true; - setNameFilters(filt); - var filt2 = filters; - filt2.push(bigger); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + }); + }); + }, + tagChangerCallback: (tag: any) => async (b: any) => { + var filt = nameFilters; + filt["t-" + tag.docsName] = b; + setNameFilters(filt); + if (b) { + var filt2 = filters; + filt2.push(tag.condition); + setFilters(filt2); + } else { + var filt2 = filters; + filt2.splice(filt2.indexOf(tag.condition), 1); + setFilters(filt2); + } + serverList.editFilters(filters); + serverList.fetchDataAndFilter().then(() => { + serverList.moveListDown(); - filt2.splice(filt2.indexOf(smaller), 1); + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - setFilters(filt2); - serverList.editFilters(filters); + serverList.currentServers.forEach((b) => { + stringList.push({ + motd: b.motd, + server: b.name, + }); + }); - serverList.fetchDataAndFilter().then(() => { - serverList.moveListDown(); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + }); + }); + }, + serverSizeChangerValueCallback: () => { + if (nameFilters["smaller-tf"]) { + return "smaller"; + } + if (nameFilters["bigger-tf"]) { + return "bigger"; + } + return "none"; + }, + serverSizeChangerCallback: (v: any) => { + toast.promise( + new Promise((g, b) => { + if (v == "smaller") { + setTemplateFilter(true); + var filt = nameFilters; + filt["smaller-tf"] = true; + filt["bigger-tf"] = false; + setNameFilters(filt); - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; + var filt2 = filters; + filt2.push(smaller); + if (filt2.includes(bigger)) { + filt2.splice(filt2.indexOf(bigger), 1); + } + setFilters(filt2); + serverList.editFilters(filters); + serverList.fetchDataAndFilter().then(() => { + serverList.moveListDown(); - serverList.currentServers.forEach((b) => { - stringList.push({ - motd: b.motd, - server: b.name, - }); - }); + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach( - (b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }, - ); - setMotdList(updatedSL); - setServers(serverList.currentServers); - g(undefined); - }); - }); - } else { - var filt = nameFilters; - filt["smaller-tf"] = false; - filt["bigger-tf"] = false; - setNameFilters(filt); - setTemplateFilter(false); + serverList.currentServers.forEach((b) => { + stringList.push({ + motd: b.motd, + server: b.name, + }); + }); - var filt2 = filters; - filt2.splice(filt2.indexOf(smaller), 1); - filt2.splice(filt2.indexOf(bigger), 1); - setFilters(filt2); - console.log(filters, filters.includes(smaller)); - serverList.editFilters(filters); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + g(undefined); + }); + }); + } else if (v == "bigger") { + setTemplateFilter(true); + var filt = nameFilters; + filt["smaller-tf"] = false; + filt["bigger-tf"] = true; + setNameFilters(filt); + var filt2 = filters; + filt2.push(bigger); - serverList.fetchDataAndFilter().then(() => { - serverList.moveListDown(); + filt2.splice(filt2.indexOf(smaller), 1); - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; + setFilters(filt2); + serverList.editFilters(filters); - serverList.currentServers.forEach((b) => { - stringList.push({ - motd: b.motd, - server: b.name, - }); - }); + serverList.fetchDataAndFilter().then(() => { + serverList.moveListDown(); - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach( - (b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }, - ); - setMotdList(updatedSL); - setServers(serverList.currentServers); - g(undefined); - }); - }); - } - }), - { - error: "Error while changing filters", - loading: "Changing filters...", - success: "Changed filters!", - }, - ); - }} - value={(() => { - if (nameFilters["smaller-tf"]) { - return "smaller"; - } else if (nameFilters["bigger-tf"]) { - return "bigger"; - } else { - return "none"; - } - })()} - > - -
- Only allow smaller servers -
- - Only allow servers that have the player range 7-15, - and cannot
- be Always Online. -
-
-
- -
- Only allow bigger servers -
- - Only allow servers with more than 15 players. - -
-
- - No/custom requirements - -
- - - - Tags - - - {allTags.map((tag) => ( -
- {tag.docsName && tag.__filter == undefined && ( - { - return nameFilters["t-" + tag.docsName]; - })()} - onCheckedChange={async (b) => { - var filt = nameFilters; - filt["t-" + tag.docsName] = b; - setNameFilters(filt); - if (b) { - var filt2 = filters; - filt2.push(tag.condition); - setFilters(filt2); - } else { - var filt2 = filters; - filt2.splice(filt2.indexOf(tag.condition), 1); - setFilters(filt2); - } - serverList.editFilters(filters); - serverList.fetchDataAndFilter().then(() => { - serverList.moveListDown(); + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; + serverList.currentServers.forEach((b) => { + stringList.push({ + motd: b.motd, + server: b.name, + }); + }); - serverList.currentServers.forEach((b) => { - stringList.push({ - motd: b.motd, - server: b.name, - }); - }); + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + g(undefined); + }); + }); + } else { + var filt = nameFilters; + filt["smaller-tf"] = false; + filt["bigger-tf"] = false; + setNameFilters(filt); + setTemplateFilter(false); - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach( - (b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }, - ); - setMotdList(updatedSL); - setServers(serverList.currentServers); - }); - }); - }} - > - - {tag.docsName} - - - )} -
- ))} - - - - Categories - - - {allCategories.map((categorie) => ( - { - var filt = nameFilters; - filt["c-" + categorie.name] = b; - setNameFilters(filt); - if (b) { - var filt2 = filters; - filt2.push(categorie.condition); - setFilters(filt2); - } else { - var filt2 = filters; - filt2.splice(filt2.indexOf(categorie.condition), 1); - setFilters(filt2); - } - serverList.editFilters(filters); - serverList.fetchDataAndFilter().then(() => { - serverList.moveListDown(); + var filt2 = filters; + filt2.splice(filt2.indexOf(smaller), 1); + filt2.splice(filt2.indexOf(bigger), 1); + setFilters(filt2); + console.log(filters, filters.includes(smaller)); + serverList.editFilters(filters); - let stringList: Array<{ - server: string; - motd: string; - }> = []; - let obj: any = {}; + serverList.fetchDataAndFilter().then(() => { + serverList.moveListDown(); - serverList.currentServers.forEach((b) => { - stringList.push({ motd: b.motd, server: b.name }); - }); + let stringList: Array<{ + server: string; + motd: string; + }> = []; + let obj: any = {}; - serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach((b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }); - setMotdList(updatedSL); - setServers(serverList.currentServers); - }); - }); - }} - checked={(() => { - return nameFilters["c-" + categorie.name]; - })()} - > - - {categorie.name} - - - ))} -
-
- - View - - - Mode - - - setPresentationMode(v as "grid" | "table") - } - > - Grid - Table - - - - - - Grid - - - { - if (am) - toast.warning( - "These settings will not change over reloads because you have account specific options enabled", - { - action: { - label: "Check settings", - onClick: () => - router.push("/account/settings/options"), - }, - }, - ); - setIPR(v); - }} - > - - 4 items per row - - - 5 items per row - - - 6 items per row - - - - - - Padding - - { - if (am) - toast.warning( - "These settings will not change over reloads because you have account specific options enabled", - { - action: { - label: "Check settings", - onClick: () => - router.push("/account/settings/options"), - }, - }, - ); - setPadding(v); - }} - > - Default - - 15px - 30px - 40px - 60px - 100px - 200px - - - - Only use padding on servers - - - - - - - Show Hero - - - router.push("/docs")}> - View the docs - - {am && ( - router.push("/account/settings")} - className="block" - > - Using saved settings in Preferences -
- - Your using settings stored on your account, that are not - temporary. - -
- )} -
-
- -
-
+ serverList.currentServers.forEach((b) => { + stringList.push({ + motd: b.motd, + server: b.name, + }); + }); - - - {randomData == undefined && <>No data to randomize} - {randomData != undefined && ( - - - {randomData.name} - {randomData.author != undefined ? ( -
- by {randomData.author} -
- ) : ( -
- )} - -
- - - {randomData.playerData.playerCount == 0 ? ( -
- ) : ( -
- )} + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + g(undefined); + }); + }); + } + }), + { + error: "Error while changing filters", + loading: "Changing filters...", + success: "Changed filters!", + } + ); + }, + }} + /> + + - - {randomData.playerData.playerCount}{" "} - {randomData.playerData.playerCount == 1 - ? "player" - : "players"}{" "} - currently online - - -
- Server IP -
-
- - {randomData.name}.minehut.gg{" "} - - - - - )} - -
+ + + {randomData == undefined && <>No data to randomize} + {randomData != undefined && ( + + + {randomData.name} + {randomData.author != undefined ? ( +
+ by {randomData.author} +
+ ) : ( +
+ )} + +
+ + + {randomData.playerData.playerCount == 0 ? ( +
+ ) : ( +
+ )} -
- {presentationMode === "grid" && ( - { - serverList.moveListDown(); - let stringList: Array<{ server: string; motd: string }> = []; - serverList.currentServers.forEach((b) => { - stringList.push({ motd: b.motd, server: b.name }); - }); + + {randomData.playerData.playerCount}{" "} + {randomData.playerData.playerCount == 1 + ? "player" + : "players"}{" "} + currently online + + +
+ Server IP +
+
+ + {randomData.name}.minehut.gg{" "} + + + + + )} + +
- serverList.getMOTDs(stringList).then((c) => { - var updatedSL = motdList; - c.forEach((b: { server: string; motd: string }) => { - updatedSL[b.server] = b.motd; - }); - setMotdList(updatedSL); - setServers(serverList.currentServers); - setLoading(false); - }); - }} - loader={} - endMessage={ -

You've seen it all", - }} - /> - } - style={{ - overflow: "hidden !important", - paddingLeft: pOS ? `${padding}px` : 6, - paddingRight: pOS ? `${padding}px` : 6, - }} - > - - {/** This looks stupid, but its the only way that works */} -

- {servers.map((b: any, i: number) => ( - <> - {/* <> +
+ {presentationMode === "grid" && ( + { + serverList.moveListDown(); + let stringList: Array<{ server: string; motd: string }> = []; + serverList.currentServers.forEach((b) => { + stringList.push({ motd: b.motd, server: b.name }); + }); + + serverList.getMOTDs(stringList).then((c) => { + var updatedSL = motdList; + c.forEach((b: { server: string; motd: string }) => { + updatedSL[b.server] = b.motd; + }); + setMotdList(updatedSL); + setServers(serverList.currentServers); + setLoading(false); + }); + }} + loader={} + endMessage={ +

+ +

+ } + style={{ + overflow: "hidden !important", + paddingLeft: pOS ? `${padding}px` : 6, + paddingRight: pOS ? `${padding}px` : 6, + }} + > + + {/** This looks stupid, but its the only way that works */} +
+ {servers.map((b: any, i: number) => ( + <> + {/* <> {i === Number(ipr) && affiliates.length != 0 && (
)} */} - - - ))} -
- - - )} - {presentationMode === "table" && ( -
- { - return ( - <> - - - - - {c.data?.name} - - - - {c.data?.name} - - - ); - }, - }, - { - field: "playerData.playerCount", - headerName: "Players", - cellRenderer: (params: CustomCellRendererProps) => { - return ( -
- {params.value == 0 ? ( -
- ) : ( -
- )}{" "} - {params.value} -
- ); - }, - }, - { - headerName: "Owner", - valueGetter: (p) => p.data?.author ?? "--", - cellRenderer: (c: CustomCellRendererProps) => { - if (c.data.author === "--") { - return <>--; - } + + + ))} +
+ + + )} + {presentationMode === "table" && ( +
+ { + return ( + <> + + + + + {c.data?.name} + + + + {c.data?.name} + + + ); + }, + }, + { + field: "playerData.playerCount", + headerName: "Players", + cellRenderer: (params: CustomCellRendererProps) => { + return ( +
+ {params.value == 0 ? ( +
+ ) : ( +
+ )}{" "} + {params.value} +
+ ); + }, + }, + { + headerName: "Owner", + valueGetter: (p) => p.data?.author ?? "--", + cellRenderer: (c: CustomCellRendererProps) => { + if (c.data.author === "--") { + return <>--; + } - return ( - <> - - {c.data?.author} - {c.data?.author} - - - ); - }, - }, - { - headerName: "Tags", - valueGetter: (p) => ( - - ), - cellRenderer: TagCR, - minWidth: 249, - }, - { - headerName: "Actions", - minWidth: 107, - cellRenderer: (c: CustomCellRendererProps) => { - return ( -
- - - - - - - - - Open up the server page to see more information - about the server - - -
- ); - }, - }, - ]} - pagination={true} - paginationPageSize={50} - paginationPageSizeSelector={[10, 25, 50, 100]} - theme={resolvedTheme === "dark" ? themeDarkWarm : themeLightWarm} - defaultColDef={{ - flex: 1, - }} - /> -
- )} -
-
- ); + return ( + <> + + {c.data?.author} + {c.data?.author} + + + ); + }, + }, + { + headerName: "Tags", + valueGetter: (p) => ( + + ), + cellRenderer: TagCR, + minWidth: 249, + }, + { + headerName: "Actions", + minWidth: 107, + cellRenderer: (c: CustomCellRendererProps) => { + return ( +
+ + + + + + + + + Open up the server page to see more information + about the server + + +
+ ); + }, + }, + ]} + pagination={true} + paginationPageSize={50} + paginationPageSizeSelector={[10, 25, 50, 100]} + theme={resolvedTheme === "dark" ? themeDarkWarm : themeLightWarm} + defaultColDef={{ + flex: 1, + }} + /> +
+ )} +
+
+ ); } export function TagCR(params: CustomCellRendererProps) { - return {params.value}; + return {params.value}; } export function TagShower(props: { - server: OnlineServer; - className?: string; - unclickable?: boolean; + server: OnlineServer; + className?: string; + unclickable?: boolean; }) { - const [loading, setLoading] = useState(true); - const [compatiableTags, setCompatiableTags] = useState< - Array<{ - name: string; - docsName?: string; - tooltip: string; - htmlDocs: string; - role: - | "default" - | "destructive" - | "outline" - | "secondary" - | "red" - | "orange" - | "yellow" - | "green" - | "lime" - | "blue" - | "teal" - | "cyan" - | "violet" - | "indigo" - | "purple" - | "fuchsia" - | "pink"; - }> - >([]); + const [loading, setLoading] = useState(true); + const [compatiableTags, setCompatiableTags] = useState< + Array<{ + name: string; + docsName?: string; + tooltip: string; + htmlDocs: string; + role: + | "default" + | "destructive" + | "outline" + | "secondary" + | "red" + | "orange" + | "yellow" + | "green" + | "lime" + | "blue" + | "teal" + | "cyan" + | "violet" + | "indigo" + | "purple" + | "fuchsia" + | "pink"; + }> + >([]); - useEffectOnce(() => { - if (loading) { - allTags.forEach((tag) => { - tag.condition(props.server).then((b) => { - if (b && tag.primary) { - tag.name(props.server).then((n) => { - compatiableTags.push({ - name: n, - docsName: tag.docsName, - tooltip: tag.tooltipDesc, - htmlDocs: tag.htmlDocs, - role: tag.role == undefined ? "secondary" : tag.role, - }); - setLoading(false); - }); - } - }); - }); - } - }); + useEffectOnce(() => { + if (loading) { + allTags.forEach((tag) => { + tag.condition(props.server).then((b) => { + if (b && tag.primary) { + tag.name(props.server).then((n) => { + compatiableTags.push({ + name: n, + docsName: tag.docsName, + tooltip: tag.tooltipDesc, + htmlDocs: tag.htmlDocs, + role: tag.role == undefined ? "secondary" : tag.role, + }); + setLoading(false); + }); + } + }); + }); + } + }); - if (loading) { - return <>; - } + if (loading) { + return <>; + } - return ( -
- {compatiableTags.map((t, i) => ( - - {props.unclickable && ( - - {t.name} - - )} - {!props.unclickable && ( - - - - - - {t.name} - - - -
- {t.tooltip} -
- Click the tag to learn more about it. -
-
-
-
- - - - {'"'} - {t.docsName == undefined ? t.name : t.docsName} - {'"'} documentation - - - - -
- )} -
- ))} -
- ); + return ( +
+ {compatiableTags.map((t, i) => ( + + {props.unclickable && ( + + {t.name} + + )} + {!props.unclickable && ( + + + + + + {t.name} + + + +
+ {t.tooltip} +
+ Click the tag to learn more about it. +
+
+
+
+ + + + {'"'} + {t.docsName == undefined ? t.name : t.docsName} + {'"'} documentation + + + + +
+ )} +
+ ))} +
+ ); } diff --git a/src/components/feat/LinkingSetup.tsx b/src/components/feat/LinkingSetup.tsx new file mode 100644 index 0000000..f04f466 --- /dev/null +++ b/src/components/feat/LinkingSetup.tsx @@ -0,0 +1,29 @@ +/* + * MHSF, Minehut Server List + * All external content is rather licensed under the ECA Agreement + * located here: https://mhsf.app/docs/legal/external-content-agreement + * + * All code under MHSF is licensed under the MIT License + * by open source contributors + * + * Copyright (c) 2024 dvelo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ \ No newline at end of file diff --git a/src/components/misc/BannerPopover.tsx b/src/components/misc/BannerPopover.tsx index b621ce4..3a4fa34 100644 --- a/src/components/misc/BannerPopover.tsx +++ b/src/components/misc/BannerPopover.tsx @@ -1,16 +1,16 @@ -"use client";; +"use client"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { Button } from "@/components/ui/button"; import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { setCustomization } from "@/lib/api"; @@ -18,73 +18,73 @@ import { toast } from "sonner"; import ColorProvider from "../ColorProvider"; const FormSchema = z.object({ - website: z - .string() - .min(2, { - message: "ID must be at least 2 characters.", - }) - .url({ message: "Image must be in URL form." }), + website: z + .string() + .min(2, { + message: "ID must be at least 2 characters.", + }) + .url({ message: "Image must be in URL form." }), }); export function BannerPopover({ server, get }: { server: string; get: any }) { - const form = useForm>({ - resolver: zodResolver(FormSchema), - defaultValues: { - website: "", - }, - }); + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + website: "", + }, + }); - async function onSubmit(data: z.infer) { - toast.promise(setCustomization(server, { banner: data.website }), { - loading: "Setting banner..", - success: "Set banner!", - error: "Error while setting banner", - }); - } + async function onSubmit(data: z.infer) { + toast.promise(setCustomization(server, { banner: data.website }), { + loading: "Setting banner..", + success: "Set banner!", + error: "Error while setting banner", + }); + } - return ( - -
- - All images that are in a web supported format can be used as the - banner for a server. - -
-
-
- - ( - - Image URL - - - - - - )} - /> - - - - -
-
- ); + return ( + +
+ + All images that are in a web supported format can be used as the + banner for a server. + +
+
+
+ + ( + + Image URL + + + + + + )} + /> + + + + +
+
+ ); } diff --git a/src/components/misc/DiscordPopover.tsx b/src/components/misc/DiscordPopover.tsx index 814d885..cded2f2 100644 --- a/src/components/misc/DiscordPopover.tsx +++ b/src/components/misc/DiscordPopover.tsx @@ -78,7 +78,7 @@ export function DiscordPopover({ server, get }: { server: string; get: any }) { }, [get]); return ( - +
To embed a Discord server into your server page, first enable the diff --git a/src/components/misc/DisplaySettings.tsx b/src/components/misc/DisplaySettings.tsx new file mode 100644 index 0000000..a346bb0 --- /dev/null +++ b/src/components/misc/DisplaySettings.tsx @@ -0,0 +1,200 @@ +"use client"; +import { CircleAlert, LayoutGrid, List, Phone } from "lucide-react"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { Switch } from "@/components/ui/switch"; +import { Label } from "@/components/ui/label"; +import { cn } from "@/lib/utils"; +import { Separator } from "@/components/ui/separator"; +import { Alert, AlertDescription, AlertTitle } from "../ui/alert"; +import { Select } from "@radix-ui/react-select"; +import { + SelectContent, + SelectGroup, + SelectItem, + SelectSeparator, + SelectTrigger, + SelectValue, +} from "../ui/select"; +import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; +import { SignedIn } from "@clerk/nextjs"; + +export function DisplaySettings({ + presentationMode, + setPresentationMode, + selectedProperties, + setSelectedProperties, + hero, + setHero, + ipr, + am, + iprChangerCallback, + padding, + paddingChangerCallback, +}: any) { + const toggleProperty = (property: string) => { + setSelectedProperties((prev: any) => + prev.includes(property) + ? prev.filter((p: any) => p !== property) + : [...prev, property] + ); + }; + + return ( +
+ +
+ + + + Grid + + + + Table + + +
+ + + +
+ + +
+
+ + + +
+ + +
+
+ + +
+ + + +
+

+ Display Properties +

+
+ {["Author", "MOTD", "Tags", "Players Online", "Actions"].map( + (property) => ( + + ) + )} +
+
+
+ + + + + Table mode isn't optimized for mobile + + At this time, we do not recommend using table mode on mobile. + + + +
+
+ ); +} diff --git a/src/components/misc/FilterMenu.tsx b/src/components/misc/FilterMenu.tsx new file mode 100644 index 0000000..cf0556c --- /dev/null +++ b/src/components/misc/FilterMenu.tsx @@ -0,0 +1,134 @@ +/* + * MHSF, Minehut Server List + * All external content is rather licensed under the ECA Agreement + * located here: https://mhsf.app/docs/legal/external-content-agreement + * + * All code under MHSF is licensed under the MIT License + * by open source contributors + * + * Copyright (c) 2024 dvelo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Badge } from "../ui/badge"; +import { allCategories, allTags } from "@/config/tags"; + +export function FilterMenu({ + serverSizeChangerCallback, + serverSizeChangerValueCallback, + templateFilter, + tagChangerValueCallback, + tagChangerCallback, + categoryChangerCallback, + categoryChangerValueCallback, + children, +}: { + children: React.ReactNode; + serverSizeChangerCallback: any; + serverSizeChangerValueCallback: any; + templateFilter: any; + tagChangerValueCallback: any; + tagChangerCallback: any; + categoryChangerCallback: any; + categoryChangerValueCallback: any; +}) { + return ( + + {children} + + + +
+ Only allow smaller servers +
+ + Only allow servers that have the player range 7-15, and cannot{" "} +
+ be Always Online. +
+
+
+ +
+ Only allow bigger servers +
+ + Only allow servers with more than 15 players. + +
+
+ + No/custom requirements + +
+ + + Tags + + {allTags.map((tag) => ( +
+ {tag.docsName && tag.__filter == undefined && ( + + + {tag.docsName} + + + )} +
+ ))} + + + Categories + + {allCategories.map((categorie) => ( + + + {categorie.name} + + + ))} +
+
+ ); +} diff --git a/src/components/misc/Footer.tsx b/src/components/misc/Footer.tsx new file mode 100644 index 0000000..a0984a2 --- /dev/null +++ b/src/components/misc/Footer.tsx @@ -0,0 +1,74 @@ +/* + * MHSF, Minehut Server List + * All external content is rather licensed under the ECA Agreement + * located here: https://mhsf.app/docs/legal/external-content-agreement + * + * All code under MHSF is licensed under the MIT License + * by open source contributors + * + * Copyright (c) 2024 dvelo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +"use client"; + +import { Book } from "lucide-react"; +import { BrandingColorfulIcon } from "../Icon"; +import { Button } from "../ui/button"; +import Github from "../ui/github"; +import { Separator } from "../ui/separator"; +import Link from "next/link"; +import { useTheme } from "next-themes"; + +export default function Footer() { + const { resolvedTheme } = useTheme(); + + return ( +
+ +

+ + + MHSF + + +

© {new Date().getFullYear()} dvelo

+ + MHSF is built on open-source technologies and is not endorsed by or + affiliated with GamerSafer or its subsidiaries.{" "} + +
+ + + + + + + + +

+
+ ); +} diff --git a/src/components/misc/NoItems.tsx b/src/components/misc/NoItems.tsx index 4a79d7d..ed71f8c 100644 --- a/src/components/misc/NoItems.tsx +++ b/src/components/misc/NoItems.tsx @@ -31,7 +31,7 @@ import { DatabaseZap } from "lucide-react"; -export default function NoItems() { +export default function NoItems({ title }: { title?: string }) { return ( <>
@@ -40,7 +40,9 @@ export default function NoItems() { size={32} />

- Huh, we tried to find something, but nothing was found. + {title + ? title + : "Huh, we tried to find something, but nothing was found."}

diff --git a/src/components/misc/ServerListInterface.tsx b/src/components/misc/ServerListInterface.tsx new file mode 100644 index 0000000..aac44bb --- /dev/null +++ b/src/components/misc/ServerListInterface.tsx @@ -0,0 +1,158 @@ +/* + * MHSF, Minehut Server List + * All external content is rather licensed under the ECA Agreement + * located here: https://mhsf.app/docs/legal/external-content-agreement + * + * All code under MHSF is licensed under the MIT License + * by open source contributors + * + * Copyright (c) 2024 dvelo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + ChevronDown, + Dices, + ListRestart, + MoreVertical, + Search, + SquareTerminal, +} from "lucide-react"; +import { FilterMenu } from "./FilterMenu"; +import { DisplaySettings } from "./DisplaySettings"; +import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; +import events from "@/lib/commandEvent"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "../ui/dropdown-menu"; + +export default function ServerListInterface({ + linksProps, + viewProps, + refreshCallback, + pickRandomServerCallback, +}: { + linksProps: { + serverSizeChangerCallback: any; + serverSizeChangerValueCallback: any; + templateFilter: any; + tagChangerValueCallback: any; + tagChangerCallback: any; + categoryChangerCallback: any; + categoryChangerValueCallback: any; + }; + viewProps: { + setPresentationMode: any; + presentationMode: any; + selectedProperties: any; + setSelectedProperties: any; + hero: any; + setHero: any; + iprChangerCallback: any; + ipr: any; + am: any; + padding: any; + paddingChangerCallback: any; + }; + refreshCallback: any; + pickRandomServerCallback: any; +}) { + return ( +
+
+
+ + + + + + + + + + + + +
+ +
+
+ + { + c.preventDefault(); + events.emit("search-request-event"); + }} + /> +
+ + + + + + + + Reload Servers + + + + Pick Random Server + + + events.emit("cmd-event")} + > + + Show Command Bar + + + +
+
+
+ ); +} diff --git a/src/components/ui/github.tsx b/src/components/ui/github.tsx index 704f108..8dca926 100644 --- a/src/components/ui/github.tsx +++ b/src/components/ui/github.tsx @@ -1,15 +1,20 @@ +import { useTheme } from "next-themes"; import type { SVGProps } from "react"; -const Github = (props: SVGProps) => ( - - - -); +const Github = (props: SVGProps) => { + const { resolvedTheme } = useTheme(); + + return ( + + + + ); +}; export default Github; diff --git a/src/config/tags.ts b/src/config/tags.ts index 30f0baf..cb7d3cb 100644 --- a/src/config/tags.ts +++ b/src/config/tags.ts @@ -294,7 +294,6 @@ async function requestServer(s: OnlineServer): Promise { const json = await re.json(); serverCache[s.name] = json.server; return json.server; - } else { - return serverCache[s.name]; } + return serverCache[s.name]; } diff --git a/src/config/version.tsx b/src/config/version.tsx index 1ea92bc..642fab2 100644 --- a/src/config/version.tsx +++ b/src/config/version.tsx @@ -30,6 +30,9 @@ "use client"; import A from "@/components/misc/Link"; +import { Button } from "@/components/ui/button"; +import Github from "@/components/ui/github"; +import Link from "next/link"; import type { ReactNode } from "react"; const User = ({ user }: { user: string }) => ( @@ -41,13 +44,22 @@ const User = ({ user }: { user: string }) => ( const FeatureList = ({ features, title, + github, }: { features: (string | ReactNode)[]; + github?: string; title: ReactNode; }) => { return (
    {title} + {github && ( + + + + )} {features.map((feature, i) => (
  • • {feature}
  • ))} @@ -55,13 +67,42 @@ const FeatureList = ({ ); }; -export const version = "1.6.50"; +export const version = "1.7.0"; export const changelog: { name: string; id: string; changelog: ReactNode }[] = [ + { + id: "38ufajf8efajwj3njdaisef", + name: "v1.7", + changelog: ( + + Version 1.7 (January 18th 2025) + + } + /> + ), + }, { id: "dut6hx3f2paswzjve4yg9r", name: "v1.6.5", changelog: ( @@ -135,6 +179,7 @@ export const changelog: { name: string; id: string; changelog: ReactNode }[] = [ name: "v1.4.0", changelog: (