mirror of
https://github.com/DeveloLongScript/MHSF.git
synced 2026-05-07 19:35:00 -05:00
bump: 0.8.0
This commit is contained in:
parent
0a620523c4
commit
b33191bdaa
BIN
public/imgs/badge1.png
Normal file
BIN
public/imgs/badge1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 739 B |
@ -69,7 +69,7 @@ export default function ServerPage({ params }: { params: { server: string } }) {
|
||||
<ColorProvider server={params.server}>
|
||||
<div className={"pt-16"}>
|
||||
<Banner server={params.server} />
|
||||
<TabServer server={params.server} tabDef="historical" />
|
||||
<TabServer server={params.server} tabDef="statistics" />
|
||||
<div className="pt-8">
|
||||
<ServerView server={params.server} />
|
||||
<div className="p-4 gap-4">
|
||||
@ -9,15 +9,17 @@ import {
|
||||
CommandSeparator,
|
||||
CommandShortcut,
|
||||
} from "@/components/ui/command";
|
||||
import { TagShower } from "./ServerList";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { OnlineServer } from "@/lib/types/mh-server";
|
||||
import events from "@/lib/commandEvent";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import {
|
||||
ArrowDown01,
|
||||
ArrowLeft,
|
||||
Calendar,
|
||||
CheckIcon,
|
||||
CommandIcon,
|
||||
Database,
|
||||
LinkIcon,
|
||||
Server,
|
||||
Settings,
|
||||
@ -27,7 +29,10 @@ import { useEffectOnce } from "@/lib/useEffectOnce";
|
||||
import { useClerk, useUser } from "@clerk/nextjs";
|
||||
import { useRouter } from "@/lib/useRouter";
|
||||
import type { SVGProps } from "react";
|
||||
import { getAccountFavorites } from "@/lib/api";
|
||||
import { favoriteServer, getAccountFavorites } from "@/lib/api";
|
||||
import IconDisplay from "./IconDisplay";
|
||||
import ServerSingle from "@/lib/single";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export function SearchCommandBar() {
|
||||
const [serverList, setServerList] = useState<OnlineServer[]>([]);
|
||||
@ -58,23 +63,46 @@ export function SearchCommandBar() {
|
||||
<CommandInput
|
||||
placeholder="Search for a server (offline or online)"
|
||||
onValueChange={(c) => {
|
||||
if (c != "") {
|
||||
fetch("https://api.minehut.com/server/" + c + "?byName=true").then(
|
||||
(l) => {
|
||||
if (l.ok) {
|
||||
console.log("found!");
|
||||
l.json().then((m: any) => {
|
||||
setSearchRes(m.server);
|
||||
console.log(searchRes);
|
||||
});
|
||||
} else {
|
||||
setSearchRes(undefined);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<CommandList>
|
||||
<CommandGroup heading="">
|
||||
<CommandGroup heading="Popular Servers">
|
||||
{serverList.map((b: OnlineServer) => (
|
||||
<CommandItem
|
||||
key={b.name}
|
||||
onSelect={() => {
|
||||
if (!backEnabled)
|
||||
events.emit("cmd-server", {
|
||||
serverName: b.name,
|
||||
serverObject: b,
|
||||
});
|
||||
if (backEnabled)
|
||||
events.emit("cmd-server-vb", {
|
||||
serverName: b.name,
|
||||
serverObject: b,
|
||||
});
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<IconDisplay server={b} className="mr-2" />
|
||||
{b.name}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
<CommandGroup heading="Hierarchy">
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
setOpen(false);
|
||||
@ -86,51 +114,148 @@ export function SearchCommandBar() {
|
||||
<span>Go back</span>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
<CommandEmpty>
|
||||
No results found. (Minehut deleted legacy servers)
|
||||
</CommandEmpty>
|
||||
{searchRes == undefined ? (
|
||||
""
|
||||
) : (
|
||||
<CommandGroup heading="Search Results">
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function ServerCommandBar() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [serverName, setServerName] = useState("");
|
||||
const [obj, setObj] = useState<OnlineServer | object>({});
|
||||
const [vb, setVB] = useState(false);
|
||||
const router = useRouter();
|
||||
const [owned, setOwned] = useState(false);
|
||||
const [serverSingle, setSingle] = useState<ServerSingle>(
|
||||
new ServerSingle(serverName)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
events.on("cmd-server", (info) => {
|
||||
serverSingle.setName(info.serverName);
|
||||
if (serverSingle != undefined)
|
||||
(serverSingle as ServerSingle).init(true).then(() => {
|
||||
setServerName(info.serverName);
|
||||
setObj(info.serverObject);
|
||||
setOpen(true);
|
||||
serverSingle.isCustomized().then((b) => setOwned(true));
|
||||
});
|
||||
});
|
||||
events.on("cmd-server-vb", (info) => {
|
||||
serverSingle.setName(info.serverName);
|
||||
setVB(true);
|
||||
if (serverSingle != undefined)
|
||||
(serverSingle as ServerSingle).init(true).then(() => {
|
||||
setServerName(info.serverName);
|
||||
setObj(info.serverObject);
|
||||
setOpen(true);
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<CommandDialog open={open} onOpenChange={setOpen}>
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
{Object.keys(obj).length != 0 && (
|
||||
<div className="m-4 dark:bg-ring min-h-[150px] rounded p-4 dark:text-white">
|
||||
<h1 className="font-bold text-2xl">
|
||||
<IconDisplay server={obj} />
|
||||
{serverName}
|
||||
</h1>
|
||||
<h1 className="text-muted-foreground">
|
||||
by {(obj as OnlineServer).author}
|
||||
</h1>
|
||||
<h2 className="flex items-center text-muted-foreground pt-[15px] pl-1.5">
|
||||
<span className="relative flex h-[10px] w-[10px]">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-black dark:bg-[#0cce6b] opacity-75" />
|
||||
<span className="relative inline-flex rounded-full h-[10px] w-[10px] bg-black dark:bg-[#0cce6b]" />
|
||||
</span>{" "}
|
||||
<span className="pl-1.5 text-[16px]">
|
||||
{(obj as OnlineServer).playerData.playerCount} online currently
|
||||
</span>
|
||||
</h2>
|
||||
<h2 className="flex items-center text-muted-foreground">
|
||||
<Calendar />
|
||||
<span className="pl-1.5 text-[16px]">
|
||||
Created in{" "}
|
||||
{timeConverter(
|
||||
(serverSingle as ServerSingle).grabOffline()?.creation
|
||||
)}
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
{owned && (
|
||||
<h2 className="flex items-center text-muted-foreground">
|
||||
<CheckIcon />
|
||||
<span className="pl-1.5 text-[16px]">
|
||||
Is customized by a MHSF User
|
||||
</span>
|
||||
</h2>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<CommandGroup heading="Server Actions">
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
router.push("/server/" + searchRes.name);
|
||||
onClick={() => router.push("/server/" + serverName + "/")}
|
||||
>
|
||||
<Server className="mr-2 h-4 w-4" />
|
||||
Open Server Page
|
||||
</CommandItem>
|
||||
<CommandItem
|
||||
onClick={() => {
|
||||
favoriteServer(serverName).then(() => toast.success("Done!"));
|
||||
}}
|
||||
>
|
||||
<div className="block">
|
||||
<span className="font-medium">{searchRes.name}</span> <br />
|
||||
<code className="text-gray-500 text-[14px]">
|
||||
{searchRes.joins} total joins •{" "}
|
||||
{searchRes.online ? "Online" : "Offline"}
|
||||
</code>
|
||||
</div>
|
||||
<Star className="mr-2 h-4 w-4" />
|
||||
Favorite Server
|
||||
</CommandItem>
|
||||
<CommandItem
|
||||
onClick={() => router.push("/server/" + serverName + "/statistics")}
|
||||
>
|
||||
<Database className="mr-2 h-4 w-4" />
|
||||
See Statistics
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
)}
|
||||
<CommandSeparator />
|
||||
<CommandGroup heading="Popular Servers">
|
||||
{serverList.map((b: OnlineServer) => (
|
||||
<CommandGroup heading="Hierarchy">
|
||||
<CommandItem
|
||||
key={b.name}
|
||||
onSelect={() => {
|
||||
router.push("/server/" + b.name);
|
||||
setOpen(false);
|
||||
if (vb) events.emit("search-request-event-back");
|
||||
if (!vb) events.emit("search-request-event");
|
||||
}}
|
||||
>
|
||||
<div className="block">
|
||||
<span className="font-medium">{b.name}</span> <br />
|
||||
<code className="text-gray-500 text-[14px]">
|
||||
<TagShower server={b} />
|
||||
</code>
|
||||
</div>
|
||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||
Go back
|
||||
</CommandItem>
|
||||
))}
|
||||
{vb && (
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
setOpen(false);
|
||||
events.emit("cmd-event");
|
||||
}}
|
||||
>
|
||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||
Back to main
|
||||
</CommandItem>
|
||||
)}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
);
|
||||
}
|
||||
|
||||
function timeConverter(UNIX_timestamp: any) {
|
||||
var a = new Date(UNIX_timestamp);
|
||||
var months = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
|
||||
var year = a.getFullYear();
|
||||
var month = months[a.getMonth()];
|
||||
var date = a.getDate();
|
||||
var time = month + "/" + date + "/" + year;
|
||||
return time;
|
||||
}
|
||||
|
||||
export function CommandBar() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const clerk = useClerk();
|
||||
@ -327,6 +452,7 @@ export function CommandBarer() {
|
||||
<SubLinkCommandBar />
|
||||
<CommandBar />
|
||||
<SearchCommandBar />
|
||||
<ServerCommandBar />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -7,18 +7,24 @@ import {
|
||||
} from "@/components/ui/tooltip";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function IconDisplay(props: { server: any }) {
|
||||
export default function IconDisplay(props: {
|
||||
server: any;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div>
|
||||
<i
|
||||
className={
|
||||
props.server.icon != null
|
||||
(props.server.icon != null
|
||||
? "icon-minecraft icon-minecraft-" +
|
||||
props.server.icon.replaceAll("_", "-").toLowerCase()
|
||||
: "icon-minecraft icon-minecraft-oak-sign"
|
||||
props.server.icon.replaceAll("_", "-").toLowerCase() +
|
||||
" "
|
||||
: "icon-minecraft icon-minecraft-oak-sign ") + props.className
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-mono">
|
||||
|
||||
@ -699,7 +699,11 @@ export default function ServerList() {
|
||||
);
|
||||
}
|
||||
|
||||
export function TagShower(props: { server: OnlineServer; className?: string }) {
|
||||
export function TagShower(props: {
|
||||
server: OnlineServer;
|
||||
className?: string;
|
||||
unclickable?: boolean;
|
||||
}) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [compatiableTags, setCompatiableTags] = useState<
|
||||
Array<{
|
||||
@ -757,6 +761,12 @@ export function TagShower(props: { server: OnlineServer; className?: string }) {
|
||||
<>
|
||||
{compatiableTags.map((t) => (
|
||||
<>
|
||||
{props.unclickable && (
|
||||
<Badge variant={t.role} className={props.className}>
|
||||
{t.name}
|
||||
</Badge>
|
||||
)}
|
||||
{!props.unclickable && (
|
||||
<Dialog key={t.name}>
|
||||
<DialogTrigger>
|
||||
<Tooltip>
|
||||
@ -789,6 +799,7 @@ export function TagShower(props: { server: OnlineServer; className?: string }) {
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
|
||||
@ -12,7 +12,6 @@ export default function TabServer({
|
||||
tabDef: string;
|
||||
}) {
|
||||
const [tab, setTab] = useState(tabDef);
|
||||
const [tabLoading, setTabLoading] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
@ -21,9 +20,8 @@ export default function TabServer({
|
||||
value={tab}
|
||||
onValueChange={(tac) => {
|
||||
setTab(tac);
|
||||
setTabLoading(true);
|
||||
if (tac == "customize") router.push(`/server/${server}/customize`);
|
||||
if (tac == "historical") router.push(`/server/${server}/short-term`);
|
||||
if (tac == "statistics") router.push(`/server/${server}/statistics`);
|
||||
if (tac == "general") router.push(`/server/${server}`);
|
||||
}}
|
||||
className="sm:w-[500px] max-sm:w-[200px]"
|
||||
@ -34,8 +32,8 @@ export default function TabServer({
|
||||
<div className="max-sm:hidden">General Information</div>
|
||||
<Home className="sm:hidden" size={18} />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="historical">
|
||||
<div className="max-sm:hidden">Short Term</div>
|
||||
<TabsTrigger value="statistics">
|
||||
<div className="max-sm:hidden">Statistics</div>
|
||||
<Database className="sm:hidden" size={18} />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="customize">
|
||||
|
||||
@ -28,7 +28,7 @@ const RadioGroupItem = React.forwardRef<
|
||||
<RadioGroupPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"aspect-square h-4 w-4 rounded-full border border-primary text-primary focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 focus:ring-4 focus:ring-neutral-300 focus:ring-offset-current dark:focus:ring-neutral-500 duration-150 ease-in-out transition-all",
|
||||
"aspect-square h-4 w-4 rounded-full border border-primary text-primary focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 focus:ring-4 focus:ring-neutral-300 focus:ring-offset-current dark:focus:ring-neutral-500 duration-150 ease-in-out transition-all ",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@ -6,15 +6,15 @@ class CommandEvents {
|
||||
}
|
||||
|
||||
// Method to emit events
|
||||
emit(eventName: string) {
|
||||
const event = new CustomEvent(eventName);
|
||||
emit(eventName: string, info?: any) {
|
||||
const event = new CustomEvent(eventName, { detail: info });
|
||||
this.eventTarget.dispatchEvent(event);
|
||||
}
|
||||
|
||||
// Method to listen for events
|
||||
on(eventName: string, callback: () => void) {
|
||||
this.eventTarget.addEventListener(eventName, () => {
|
||||
callback();
|
||||
on(eventName: string, callback: (info?: any) => void) {
|
||||
this.eventTarget.addEventListener(eventName, (infoF?: any) => {
|
||||
callback(infoF.detail);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { serverOwned } from "./api";
|
||||
import { OnlineServer, ServerResponse } from "./types/mh-server";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
@ -10,7 +11,15 @@ export default class ServerSingle {
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
}
|
||||
init(): Promise<boolean> {
|
||||
setName(newName: string) {
|
||||
this.name = newName;
|
||||
}
|
||||
|
||||
isCustomized(): Promise<boolean> {
|
||||
return serverOwned(this.name);
|
||||
}
|
||||
|
||||
init(skipOnline?: boolean): Promise<boolean> {
|
||||
return new Promise<boolean>((g, bc) => {
|
||||
fetch("https://api.minehut.com/server/" + this.name + "?byName=true")
|
||||
.then((d) => {
|
||||
@ -18,7 +27,7 @@ export default class ServerSingle {
|
||||
d.json().then((m) => {
|
||||
this.online = m.server.online;
|
||||
this.offlineObj = m.server;
|
||||
if (this.online == true) {
|
||||
if (this.online == true && skipOnline != true) {
|
||||
fetch("https://api.minehut.com/servers").then((l) =>
|
||||
l.json().then((o) => {
|
||||
o.servers.forEach((j: OnlineServer) => {
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
export const version = "b-0.7.2";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export const version = "b-0.8.0";
|
||||
|
||||
const User = ({ user }: { user: string }) => (
|
||||
<span className="cursor-pointer bg-[rgba(255,165,0,0.25);] rounded p-[2.5px]">
|
||||
@ -41,6 +44,16 @@ export const Changelog = () => (
|
||||
</code>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<strong className="flex items-center">
|
||||
Version b-0.8.0 (August 11th 2024)
|
||||
</strong>
|
||||
<ul>
|
||||
<li>• Fixing up command bar</li>
|
||||
<li>• Renaming "Short Term" to "Statistics"</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<strong className="flex items-center">
|
||||
Version b-0.7.2 (August 7th 2024)
|
||||
@ -118,5 +131,11 @@ export const Changelog = () => (
|
||||
<li>• Inital release!</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br />
|
||||
<div className="w-full justify-center">
|
||||
<Link href="https://dvelo.vercel.app">
|
||||
<Image src="/imgs/badge1.png" alt="cool badge" width={88} height={31} />
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user