mirror of
https://github.com/DeveloLongScript/MHSF.git
synced 2026-05-09 07:14:59 -05:00
Compare commits
4 Commits
24488494ae
...
7d0bb44568
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d0bb44568 | |||
| b62f79e010 | |||
| f21ce33b27 | |||
| bbc092be1f |
@ -63,7 +63,6 @@ const nextConfig = {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
experimental: {
|
||||
missingSuspenseWithCSRBailout: false,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
"name": "mhsf",
|
||||
"version": "1.3.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@ -43,8 +44,8 @@
|
||||
"@trpc/react-query": "^11.0.0",
|
||||
"@trpc/server": "^11.0.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"@types/react": "19.0.10",
|
||||
"@types/react-dom": "19.0.4",
|
||||
"@types/request-ip": "^0.0.41",
|
||||
"@unocss/eslint-plugin": "^0.61.5",
|
||||
"@unocss/postcss": "^0.61.5",
|
||||
@ -71,7 +72,7 @@
|
||||
"monaco-editor": "^0.52.2",
|
||||
"mongodb": "^6.8.0",
|
||||
"motion": "^12.7.4",
|
||||
"next": "15.2.0",
|
||||
"next": "^15.3.1",
|
||||
"next-contentlayer": "^0.3.4",
|
||||
"next-css-obfuscator": "^2.2.16",
|
||||
"next-sitemap": "^4.2.3",
|
||||
@ -81,8 +82,8 @@
|
||||
"nuqs": "^2.4.1",
|
||||
"postcss-obfuscator": "^1.6.1",
|
||||
"prettier": "^3.3.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-fade-in": "^2.0.1",
|
||||
"react-fast-marquee": "^1.6.5",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
@ -109,18 +110,18 @@
|
||||
"@clerk/themes": "^2.1.19",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@radix-ui/react-checkbox": "^1.1.1",
|
||||
"@radix-ui/react-context-menu": "^2.1.5",
|
||||
"@radix-ui/react-dialog": "^1.1.2",
|
||||
"@radix-ui/react-context-menu": "^2.2.6",
|
||||
"@radix-ui/react-dialog": "^1.1.6",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-radio-group": "^1.2.0",
|
||||
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||
"@radix-ui/react-separator": "^1.1.0",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-tabs": "^1.1.0",
|
||||
"@radix-ui/react-tooltip": "^1.1.3",
|
||||
"@radix-ui/react-separator": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.2.0",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@tailwindcss/postcss": "^4.0.7",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/canvas-confetti": "^1.6.4",
|
||||
@ -135,12 +136,12 @@
|
||||
"@vercel/analytics": "^1.3.1",
|
||||
"@vercel/speed-insights": "^1.0.12",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "15.2.0",
|
||||
"framer-motion": "^11.3.8",
|
||||
"framer-motion": "^12.7.4",
|
||||
"geist": "^1.3.0",
|
||||
"mangle-css-class-webpack-plugin": "^5.1.0",
|
||||
"postcss": "^8",
|
||||
@ -149,12 +150,12 @@
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-resizable-panels": "^2.0.23",
|
||||
"recharts": "^2.12.7",
|
||||
"recharts": "^2.15.1",
|
||||
"shiki": "^1.23.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tailwindcss": "^4.0.7",
|
||||
"typescript": "^5",
|
||||
"vaul": "^0.9.1",
|
||||
"zod": "^3.23.8"
|
||||
"vaul": "^1.1.2",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "19.0.10",
|
||||
|
||||
@ -1,148 +0,0 @@
|
||||
/*
|
||||
* 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) 2025 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 "../../globals.css";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { Placeholder } from "@/components/ui/placeholder";
|
||||
import { Command, X } from "lucide-react";
|
||||
import { IsScript } from "@/components/util/is-script";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Link from "next/link";
|
||||
import { NavBar } from "@/components/feat/navbar/navbar";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { ThemeProvider } from "@/components/util/theme-provider";
|
||||
import { FontBoundary } from "@/components/util/font-boundary";
|
||||
import { ClerkProvider } from "@/components/util/clerk-provider";
|
||||
import { Toaster } from "sonner";
|
||||
import { Footer } from "@/components/feat/footer/footer";
|
||||
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
||||
import { IframeProtector } from "@/components/util/iframe-protector";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/components/ui/sidebar";
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const searchParams = useSearchParams();
|
||||
const search = searchParams?.get("theme") || "light";
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<noscript>
|
||||
<main className="flex justify-center items-center text-center min-h-screen h-max">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="JavaScript is required for MHSF"
|
||||
description="MHSF cannot grab servers or do other external requests without JavaScript."
|
||||
>
|
||||
<Link href="https://www.enable-javascript.com/">
|
||||
<Button>Here's how</Button>
|
||||
</Link>
|
||||
</Placeholder>
|
||||
</main>
|
||||
</noscript>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<ClerkProvider>
|
||||
<IsScript>
|
||||
<NuqsAdapter>
|
||||
<FontBoundary>
|
||||
<TooltipProvider>
|
||||
<SidebarProvider>
|
||||
<Sidebar variant="inset">
|
||||
<SidebarHeader>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton size="lg" asChild>
|
||||
<a href="#">
|
||||
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
||||
<Command className="size-4" />
|
||||
</div>
|
||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||
<span className="truncate font-semibold">
|
||||
Acme Inc
|
||||
</span>
|
||||
<span className="truncate text-xs">
|
||||
Enterprise
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild size="sm">
|
||||
<a href="#">
|
||||
<span>a</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
<SidebarInset>
|
||||
<Toaster richColors position="bottom-center" />
|
||||
<div className="overflow-x-hidden">{children}</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
</TooltipProvider>
|
||||
</FontBoundary>
|
||||
</NuqsAdapter>
|
||||
</IsScript>
|
||||
</ClerkProvider>
|
||||
</ThemeProvider>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@ -46,8 +46,7 @@ export default function RootLayout({
|
||||
const search = searchParams?.get("theme") || "light";
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
disableTransitionOnChange
|
||||
@ -55,7 +54,6 @@ export default function RootLayout({
|
||||
>
|
||||
<TooltipProvider>{children}</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -28,14 +28,8 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
"use client";
|
||||
import "../globals.css";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { Placeholder } from "@/components/ui/placeholder";
|
||||
import { X } from "lucide-react";
|
||||
import { IsScript } from "@/components/util/is-script";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Link from "next/link";
|
||||
import { NavBar } from "@/components/feat/navbar/navbar";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { ThemeProvider } from "@/components/util/theme-provider";
|
||||
@ -50,24 +44,9 @@ export default function RootLayout({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const searchParams = useSearchParams();
|
||||
const search = searchParams?.get("theme") || "light";
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<noscript>
|
||||
<main className="flex justify-center items-center text-center min-h-screen h-max">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="JavaScript is required for MHSF"
|
||||
description="MHSF cannot grab servers or do other external requests without JavaScript."
|
||||
>
|
||||
<Link href="https://www.enable-javascript.com/">
|
||||
<Button>Here's how</Button>
|
||||
</Link>
|
||||
</Placeholder>
|
||||
</main>
|
||||
</noscript>
|
||||
<>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
@ -91,6 +70,6 @@ export default function RootLayout({
|
||||
</IsScript>
|
||||
</ClerkProvider>
|
||||
</ThemeProvider>
|
||||
</html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -56,20 +56,7 @@ export default function RootLayout({
|
||||
const search = searchParams?.get("theme") || "light";
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<noscript>
|
||||
<main className="flex justify-center items-center text-center min-h-screen h-max">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="JavaScript is required for MHSF"
|
||||
description="MHSF cannot grab servers or do other external requests without JavaScript."
|
||||
>
|
||||
<Link href="https://www.enable-javascript.com/">
|
||||
<Button>Here's how</Button>
|
||||
</Link>
|
||||
</Placeholder>
|
||||
</main>
|
||||
</noscript>
|
||||
<>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
@ -93,6 +80,6 @@ export default function RootLayout({
|
||||
</IsScript>
|
||||
</ClerkProvider>
|
||||
</ThemeProvider>
|
||||
</html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -134,6 +134,7 @@ export default function ModificationPage({
|
||||
activatedModifications: modificationArray
|
||||
}
|
||||
});
|
||||
communicator.send("rerender-servers", {});
|
||||
}}>
|
||||
{modObj?.active ? "Disable" : "Enable"}
|
||||
</Button>
|
||||
@ -165,6 +166,7 @@ export default function ModificationPage({
|
||||
});
|
||||
toast.success(`Deleted in ${Date.now() - time}ms`);
|
||||
router.push(backRoute);
|
||||
communicator.send("rerender-servers", {});
|
||||
}}
|
||||
>
|
||||
<Trash size={16} /> Delete
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
|
||||
@plugin 'tailwindcss-animate';
|
||||
@config '../../tailwind-hero.config.ts';
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@ -78,8 +79,10 @@
|
||||
border-color: hsl(214.3 31.8% 91.4%);
|
||||
}
|
||||
|
||||
--sidebar: hsl(0 0% 98%)
|
||||
--sidebar: hsl(0 0% 98%);
|
||||
|
||||
}
|
||||
|
||||
.dark {
|
||||
--border: 216 34% 17%;
|
||||
--background: 0 0% 3.9%;
|
||||
@ -404,6 +407,9 @@ body {
|
||||
padding-left: 20px;
|
||||
color: var(--mauve-11);
|
||||
}
|
||||
.slot[data-swapy-highlighted] {
|
||||
@apply bg-muted rounded transition-all
|
||||
}
|
||||
.icon-minecraft,
|
||||
.icon-minecraft-sm {
|
||||
display: inline-block;
|
||||
|
||||
@ -28,27 +28,38 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
"use client";
|
||||
import { Placeholder } from "@/components/ui/placeholder";
|
||||
import "./globals.css";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { Inter } from "next/font/google";
|
||||
import { X } from "lucide-react";
|
||||
import { Link } from "@/components/util/link";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const searchParams = useSearchParams();
|
||||
const search = searchParams?.get("theme") || "light";
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<noscript>{children}</noscript>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<noscript>
|
||||
<main className="flex justify-center items-center text-center min-h-screen h-max">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="JavaScript is required for MHSF"
|
||||
description="MHSF cannot grab servers or do other external requests without JavaScript."
|
||||
>
|
||||
<Link href="https://www.enable-javascript.com/" noExtraIcons>
|
||||
<Button>Here's how</Button>
|
||||
</Link>
|
||||
</Placeholder>
|
||||
</main>
|
||||
</noscript>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@ -27,7 +27,17 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
"use client";
|
||||
|
||||
export default function Dashboard() {
|
||||
return <>Hello world</>
|
||||
}
|
||||
import { NotFoundComponent } from "@/components/util/not-found";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
applicationName: "MHSF",
|
||||
title: "Page not found · MHSF",
|
||||
description: "Couldn't find the page that was requested.",
|
||||
};
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return <NotFoundComponent />;
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
import { ComponentPropsWithoutRef, ReactNode } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface BentoGridProps extends ComponentPropsWithoutRef<"div"> {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface BentoCardProps extends ComponentPropsWithoutRef<"div"> {
|
||||
name: string;
|
||||
className: string;
|
||||
background: ReactNode;
|
||||
Icon: React.ElementType;
|
||||
description: string;
|
||||
href: string;
|
||||
cta: string;
|
||||
}
|
||||
|
||||
const BentoGrid = ({ children, className, ...props }: BentoGridProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"grid w-full auto-rows-[22rem] grid-cols-3 gap-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const BentoCard = ({
|
||||
name,
|
||||
className,
|
||||
background,
|
||||
Icon,
|
||||
description,
|
||||
href,
|
||||
cta,
|
||||
...props
|
||||
}: BentoCardProps) => (
|
||||
<div
|
||||
key={name}
|
||||
className={cn(
|
||||
"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl",
|
||||
// light styles
|
||||
"bg-background [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]",
|
||||
// dark styles
|
||||
"transform-gpu dark:bg-background dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div>{background}</div>
|
||||
<div className="pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10">
|
||||
<Icon className="h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75" />
|
||||
<h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">
|
||||
{name}
|
||||
</h3>
|
||||
<p className="max-w-lg text-neutral-400">{description}</p>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export { BentoCard, BentoGrid };
|
||||
@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
import { BrandingGenericIcon, Discord } from "../icons/branding-icons";
|
||||
import { Link } from "../../util/link";
|
||||
import { FooterStatus } from "./status";
|
||||
@ -7,10 +8,11 @@ import Github from "@/components/ui/github";
|
||||
import Image from "next/image"
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
const hideFooterPages = ["/home"];
|
||||
const hideFooterPages = ["/home"]
|
||||
|
||||
export function Footer() {
|
||||
const pathname = usePathname();
|
||||
|
||||
if (!hideFooterPages.includes(pathname ?? ""))
|
||||
return (
|
||||
<footer className="w-full mt-15 border-t border-neutral-500/20 bg-neutral-100 dark:border-neutral-700/50 dark:bg-neutral-900 text-muted-foreground">
|
||||
@ -50,7 +52,7 @@ export function Footer() {
|
||||
<div className="flex items-center mb-2 justify-end gap-2">
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="tertiary" size="square-md" className="flex items-center">
|
||||
<Discord className="w-[1.25em] h-[1.25em]" />
|
||||
</Button>
|
||||
|
||||
@ -90,8 +90,6 @@ export function FontChanger({
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
console.log(position);
|
||||
|
||||
return (
|
||||
<div className="h-[1.2em] overflow-hidden flex items-center justify-center">
|
||||
<span
|
||||
|
||||
@ -106,13 +106,13 @@ export default function HomePageComponent() {
|
||||
style={
|
||||
{
|
||||
"--gradient-color-1":
|
||||
resolvedTheme === "dark" ? "#043D5D" : "#1F9EA3",
|
||||
resolvedTheme === "dark" ? "#470061" : "#610034",
|
||||
"--gradient-color-2":
|
||||
resolvedTheme === "dark" ? "#032E46" : "#F8BD97",
|
||||
resolvedTheme === "dark" ? "#001299" : "#700099",
|
||||
"--gradient-color-3":
|
||||
resolvedTheme === "dark" ? "#23B684" : "#9E5428",
|
||||
resolvedTheme === "dark" ? "#8d00eb" : "#eb00ac",
|
||||
"--gradient-color-4":
|
||||
resolvedTheme === "dark" ? "#0F595E" : "#EEEEEE",
|
||||
resolvedTheme === "dark" ? "#009de0" : "#0007e0",
|
||||
webKitMaskImage:
|
||||
"linear-gradient(to top, black, black, transparent)",
|
||||
maskImage: "linear-gradient(to top, black, black, transparent)",
|
||||
|
||||
@ -30,22 +30,22 @@
|
||||
|
||||
"use client";
|
||||
import {
|
||||
BrandingGenericIcon,
|
||||
brandingIconClipboard,
|
||||
BrandingGenericIcon,
|
||||
brandingIconClipboard,
|
||||
} from "@/components/feat/icons/branding-icons";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuTrigger,
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuTrigger,
|
||||
} from "@/components/ui/context-menu";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import Github from "@/components/ui/github";
|
||||
import { Link } from "@/components/util/link";
|
||||
@ -63,143 +63,147 @@ import { usePathname } from "next/navigation";
|
||||
const animatedTopbarPages = ["/home"];
|
||||
|
||||
export function NavBar() {
|
||||
const showBorder = useScroll(40);
|
||||
const clipboard = useClipboard();
|
||||
const pathname = usePathname();
|
||||
const { user } = useUser();
|
||||
const showBorder = useScroll(40);
|
||||
const clipboard = useClipboard();
|
||||
const pathname = usePathname();
|
||||
const { user } = useUser();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"w-screen h-[3rem] grid-cols-3 fixed z-10 flex",
|
||||
"items-center justify-self-start me-auto pl-4 flex-1 transition-all justify-between",
|
||||
"lg:top-0 max-lg:bottom-0",
|
||||
showBorder ? "border-b backdrop-blur-xl" : "max-lg:border-b max-lg:backdrop-blur-xl",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:1000ms] opacity-0 animate-fade-in"
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger>
|
||||
<Link className="gap-5 flex items-center " href="/">
|
||||
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] mt-0.5" />
|
||||
<span className="gap-2 flex group hover:text-blue-500 hover:underline transition-all">
|
||||
<strong className="">MHSF</strong>
|
||||
<span className="text-muted-foreground group-hover:text-blue-500 transition-all">
|
||||
v{version}
|
||||
</span>
|
||||
</span>
|
||||
</Link>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent className="overflow-hidden min-w-[300px]">
|
||||
<DropdownMenuSeparator>Platform</DropdownMenuSeparator>
|
||||
<Link href="Special:Root">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<ServerCrash size={16} /> Go to Dynamic Home Page
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"w-screen h-[3rem] grid-cols-3 fixed z-10 flex",
|
||||
"items-center justify-self-start me-auto pl-4 flex-1 transition-all justify-between",
|
||||
"lg:top-0 max-lg:bottom-0",
|
||||
showBorder
|
||||
? "border-b backdrop-blur-xl"
|
||||
: "max-lg:border-b max-lg:backdrop-blur-xl",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:1000ms] opacity-0 animate-fade-in"
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger>
|
||||
<Link className="gap-5 flex items-center " href="/">
|
||||
<BrandingGenericIcon className="max-w-[32px] max-h-[32px] mt-0.5" />
|
||||
<span className="gap-2 flex group hover:text-blue-500 hover:underline transition-all">
|
||||
<strong className="">MHSF</strong>
|
||||
<span className="text-muted-foreground group-hover:text-blue-500 transition-all">
|
||||
v{version}
|
||||
</span>
|
||||
</span>
|
||||
</Link>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent className="overflow-hidden min-w-[300px]">
|
||||
<DropdownMenuSeparator>Platform</DropdownMenuSeparator>
|
||||
<Link href="Special:Root">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<ServerCrash size={16} /> Go to Dynamic Home Page
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
|
||||
<Link href="/home">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Home size={16} /> Go to Home Page
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
<ContextMenuSeparator />
|
||||
<Link href="/home">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Home size={16} /> Go to Home Page
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
<ContextMenuSeparator />
|
||||
|
||||
<ContextMenuItem
|
||||
onClick={() => {
|
||||
clipboard.writeText(brandingIconClipboard);
|
||||
toast.success("Copied icon to clipboard!");
|
||||
}}
|
||||
>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Image size={16} /> Copy Logo as SVG
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuSeparator />
|
||||
<Link href="Special:GitHub">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Github /> Open GitHub
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
<Link href="Special:GitHub/releases">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Github /> Open GitHub Releases
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
</span>
|
||||
<span className="mr-3 flex items-center">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<SignedOut>
|
||||
<Button
|
||||
className={cn(
|
||||
"rounded-full flex items-center",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
|
||||
: ""
|
||||
)}
|
||||
size="square-lg"
|
||||
variant="secondary"
|
||||
>
|
||||
<Menu size={16} />
|
||||
</Button>
|
||||
</SignedOut>
|
||||
<SignedIn>
|
||||
<Button
|
||||
size="square-lg"
|
||||
variant="tertiary"
|
||||
className={cn(
|
||||
"rounded-full flex items-center",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
<NextImage
|
||||
alt="Clerk Image"
|
||||
src={
|
||||
user?.imageUrl === undefined
|
||||
? "https://img.clerk.com/preview.png?size=144&seed=seed&initials=AD&isSquare=true&bgType=marble&bgColor=6c47ff&fgType=silhouette&fgColor=FFFFFF&type=user&w=48&q=75"
|
||||
: user?.imageUrl
|
||||
}
|
||||
width={26}
|
||||
height={26}
|
||||
className="rounded-full"
|
||||
/>
|
||||
</Button>
|
||||
</SignedIn>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="max-w-[280px] w-[280px] mt-2 mr-2">
|
||||
<MenuDropdown />
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<SignedIn>
|
||||
<div
|
||||
className="absolute right-0 -z-10 h-full
|
||||
<ContextMenuItem
|
||||
onClick={() => {
|
||||
clipboard.writeText(brandingIconClipboard);
|
||||
toast.success("Copied icon to clipboard!");
|
||||
}}
|
||||
>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Image size={16} /> Copy Logo as SVG
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuSeparator />
|
||||
<Link href="Special:GitHub">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Github /> Open GitHub
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
<Link href="Special:GitHub/releases">
|
||||
<ContextMenuItem>
|
||||
<span className="pl-2 flex gap-2 items-center">
|
||||
<Github /> Open GitHub Releases
|
||||
</span>
|
||||
</ContextMenuItem>
|
||||
</Link>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
</span>
|
||||
<span className="mr-3 flex items-center">
|
||||
<DropdownMenu>
|
||||
<SignedOut>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
className={cn(
|
||||
"rounded-full flex items-center",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
|
||||
: "",
|
||||
)}
|
||||
size="square-lg"
|
||||
variant="secondary"
|
||||
>
|
||||
<Menu size={16} />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
</SignedOut>
|
||||
<SignedIn>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="square-lg"
|
||||
variant="tertiary"
|
||||
className={cn(
|
||||
"rounded-full flex items-center",
|
||||
pathname !== null && animatedTopbarPages.includes(pathname)
|
||||
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
<NextImage
|
||||
alt="Clerk Image"
|
||||
src={
|
||||
user?.imageUrl === undefined
|
||||
? "https://img.clerk.com/preview.png?size=144&seed=seed&initials=AD&isSquare=true&bgType=marble&bgColor=6c47ff&fgType=silhouette&fgColor=FFFFFF&type=user&w=48&q=75"
|
||||
: user?.imageUrl
|
||||
}
|
||||
width={26}
|
||||
height={26}
|
||||
className="rounded-full"
|
||||
/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
</SignedIn>
|
||||
<DropdownMenuContent className="max-w-[280px] w-[280px] mt-2 mr-2">
|
||||
<MenuDropdown />
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<SignedIn>
|
||||
<div
|
||||
className="absolute right-0 -z-10 h-full
|
||||
overflow-hidden w-full ml-auto"
|
||||
style={{ borderRadius: "inherit" }}
|
||||
>
|
||||
<img
|
||||
src={user?.imageUrl ?? ""}
|
||||
className="blur-2xl -z-10 object-cover w-48 h-48 opacity-20 dark:opacity-50 ml-auto"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</SignedIn>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
style={{ borderRadius: "inherit" }}
|
||||
>
|
||||
<img
|
||||
src={user?.imageUrl ?? ""}
|
||||
className="blur-2xl -z-10 object-cover w-48 h-48 opacity-20 dark:opacity-50 ml-auto"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</SignedIn>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,25 +2,135 @@ import { Button } from "@/components/ui/button";
|
||||
import type { Filter } from "@/lib/types/filter";
|
||||
import type { Sort } from "@/lib/types/sort";
|
||||
import { ModificationFileCreationDialog } from "./modification-file-creation-dialog";
|
||||
import { useUser } from "@clerk/nextjs";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useIframeCommunication } from "@/lib/hooks/use-iframe-communication";
|
||||
|
||||
type Action = Filter | Sort | { customAction: string };
|
||||
|
||||
export type ClerkEmbeddedFilter<T> = {
|
||||
type: string;
|
||||
metadata: T;
|
||||
};
|
||||
|
||||
export function ModificationAction({ value }: { value?: Action }) {
|
||||
return (
|
||||
<>
|
||||
{value !== undefined && "customAction" in value ? (
|
||||
<ModificationFileCreationDialog
|
||||
type={value.customAction.endsWith("sort") ? "sort" : "filter"}
|
||||
>
|
||||
<Button size="sm" className="mt-1">
|
||||
{value.customAction === "custom-sort"
|
||||
? "Create Sort"
|
||||
: "Create Filter"}
|
||||
</Button>
|
||||
</ModificationFileCreationDialog>
|
||||
) : (
|
||||
<Button size="sm">Apply</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
const { isSignedIn, user } = useUser();
|
||||
const [applied, setApplied] = useState<number | undefined>();
|
||||
const communication = useIframeCommunication();
|
||||
|
||||
const findExisting = () => {
|
||||
if (!(value !== undefined && "customAction" in value)) {
|
||||
const filter = value as Filter;
|
||||
let existing = -1;
|
||||
if (isSignedIn)
|
||||
existing = (
|
||||
(user.unsafeMetadata.filters as Array<
|
||||
ClerkEmbeddedFilter<unknown>
|
||||
>) ?? []
|
||||
).findIndex(
|
||||
(c) =>
|
||||
JSON.stringify(c.metadata) ===
|
||||
JSON.stringify(filter.toIdentifier()) &&
|
||||
c.type === filter.getSpecificFilterId(),
|
||||
);
|
||||
else
|
||||
existing = (
|
||||
(JSON.parse(localStorage.getItem("mhsf__filters") ?? "[]") as Array<
|
||||
ClerkEmbeddedFilter<unknown>
|
||||
>) ?? []
|
||||
).findIndex(
|
||||
(c) =>
|
||||
JSON.stringify(c.metadata) === JSON.stringify(filter.toIdentifier()) &&
|
||||
c.type === filter.getSpecificFilterId(),
|
||||
);
|
||||
return existing;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
useEffect(() => setApplied(findExisting()))
|
||||
|
||||
return (
|
||||
<>
|
||||
{value !== undefined && "customAction" in value ? (
|
||||
<ModificationFileCreationDialog
|
||||
type={value.customAction.endsWith("sort") ? "sort" : "filter"}
|
||||
>
|
||||
<Button size="sm" className="mt-1">
|
||||
{value.customAction === "custom-sort"
|
||||
? "Create Sort"
|
||||
: "Create Filter"}
|
||||
</Button>
|
||||
</ModificationFileCreationDialog>
|
||||
) : (
|
||||
<Button
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
onClick={async () => {
|
||||
if (value?.type() === "filter") {
|
||||
const filter = value as Filter;
|
||||
const existing = findExisting();
|
||||
|
||||
if (isSignedIn) {
|
||||
const existingArray =
|
||||
(user.unsafeMetadata.filters as Array<
|
||||
ClerkEmbeddedFilter<unknown>
|
||||
>) ?? [];
|
||||
existingArray.splice(existing, 1);
|
||||
if (existing === -1)
|
||||
await user.update({
|
||||
unsafeMetadata: {
|
||||
...user.unsafeMetadata,
|
||||
filters: [
|
||||
{
|
||||
type: filter.getSpecificFilterId(),
|
||||
metadata: filter.toIdentifier(),
|
||||
},
|
||||
...((user.unsafeMetadata.filters as Array<
|
||||
ClerkEmbeddedFilter<unknown>
|
||||
>) ?? []),
|
||||
] as Array<ClerkEmbeddedFilter<unknown>>,
|
||||
},
|
||||
});
|
||||
else
|
||||
await user.update({
|
||||
unsafeMetadata: {
|
||||
filters: existingArray,
|
||||
...user.unsafeMetadata,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const existingArray =
|
||||
(JSON.parse(
|
||||
localStorage.getItem("mhsf__filters") ?? "[]",
|
||||
) as Array<ClerkEmbeddedFilter<unknown>>) ?? [];
|
||||
existingArray.splice(existing, 1);
|
||||
|
||||
if (existing === -1)
|
||||
localStorage.setItem(
|
||||
"mhsf__filters",
|
||||
JSON.stringify([
|
||||
{
|
||||
type: filter.getSpecificFilterId(),
|
||||
metadata: filter.toIdentifier(),
|
||||
},
|
||||
...((JSON.parse(
|
||||
localStorage.getItem("mhsf__filters") ?? "[]",
|
||||
) as Array<ClerkEmbeddedFilter<unknown>>) ?? []),
|
||||
]),
|
||||
);
|
||||
else
|
||||
localStorage.setItem("mhsf__filters", JSON.stringify(existingArray));
|
||||
}
|
||||
|
||||
setApplied(findExisting());
|
||||
}
|
||||
communication.fromIframe.send("rerender-servers", {});
|
||||
}}
|
||||
>
|
||||
{applied === -1 ? "A" : "Una"}pply
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -41,6 +41,9 @@ export function ModificationFrame() {
|
||||
if (c.from === "iframe")
|
||||
communication.toIframe.send("ping", {from: "top-layer"})
|
||||
})
|
||||
communication.toIframe.handle("rerender-servers", (c) => {
|
||||
window.dispatchEvent(new Event("update-modification-stack"))
|
||||
})
|
||||
}, [ref])
|
||||
|
||||
return <iframe ref={ref} src="/servers/embedded/sl-modification-frame" height={800} title="Server-list Modification Frame" />
|
||||
|
||||
@ -36,37 +36,92 @@ import { miniMessage } from "minimessage-js";
|
||||
import { toast } from "sonner";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Material } from "@/components/ui/material";
|
||||
import { useState } from "react";
|
||||
import { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
|
||||
import Markdown from "react-markdown";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Ellipsis, EllipsisVertical, Shuffle } from "lucide-react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { RearrangeDrawer } from "../rearrange/rearrange-drawer";
|
||||
|
||||
export function MOTDRow({ server }: { server: ServerResponse }) {
|
||||
const clipboard = useClipboard();
|
||||
export function MOTDRow({
|
||||
server,
|
||||
mhsfData,
|
||||
}: { server: ServerResponse; mhsfData: ReturnType<typeof useMHSFServer> }) {
|
||||
const clipboard = useClipboard();
|
||||
const [tab, setTab] = useState("motd");
|
||||
|
||||
return (
|
||||
<Material className="p-4 relative h-[250px]">
|
||||
<strong className="text-lg">MOTD</strong>
|
||||
<br />
|
||||
<Separator className="my-2" />
|
||||
<MOTDRenderer
|
||||
className={cn("mt-2 break-all overflow-y-auto max-h-[150px]")}
|
||||
minecraftFont
|
||||
>
|
||||
{server.motd}
|
||||
</MOTDRenderer>
|
||||
<br />
|
||||
<small className="absolute bottom-[10px]">
|
||||
{server.motd.length} characters,{" "}
|
||||
<button
|
||||
className="cursor-pointer underline"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clipboard.writeText(
|
||||
miniMessage().toHTML(miniMessage().deserialize(server.motd))
|
||||
);
|
||||
toast.success("Copied to clipboard.");
|
||||
}}
|
||||
>
|
||||
click to copy HTML
|
||||
</button>
|
||||
</small>
|
||||
</Material>
|
||||
);
|
||||
return (
|
||||
<Material className="p-4 relative h-[250px]">
|
||||
<span className="flex gap-4 justify-between items-center">
|
||||
<span className="flex gap-4 items-center">
|
||||
<strong className="text-lg max-lg:hidden">
|
||||
{tab === "motd" ? "MOTD" : "Description"}
|
||||
</strong>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"text-sm cursor-pointer hover:bg-slate-100 dark:hover:bg-zinc-700/30 transition-all duration-75 disabled:opacity-50 disabled:pointer-events-none",
|
||||
"rounded-xl px-2 flex items-center gap-2",
|
||||
tab === "motd" && "bg-slate-100 dark:bg-zinc-700/30 font-medium",
|
||||
)}
|
||||
onClick={() => setTab("motd")}
|
||||
>
|
||||
MOTD
|
||||
</button>
|
||||
{mhsfData.server?.customizationData.description !== undefined && (
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"text-sm cursor-pointer hover:bg-slate-100 dark:hover:bg-zinc-700/30 transition-all duration-75 disabled:opacity-50 disabled:pointer-events-none",
|
||||
"rounded-xl px-2 flex items-center gap-2",
|
||||
tab === "description" &&
|
||||
"bg-slate-100 dark:bg-zinc-700/30 font-medium",
|
||||
)}
|
||||
onClick={() => setTab("description")}
|
||||
>
|
||||
Description
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<Separator className="my-2" />
|
||||
{tab === "motd" && (
|
||||
<>
|
||||
<MOTDRenderer
|
||||
className={cn("mt-2 break-all overflow-y-auto max-h-[150px]")}
|
||||
minecraftFont
|
||||
>
|
||||
{server.motd}
|
||||
</MOTDRenderer>
|
||||
<br />
|
||||
<small className="absolute bottom-[10px]">
|
||||
{server.motd.length} characters,{" "}
|
||||
<button
|
||||
className="cursor-pointer underline"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clipboard.writeText(
|
||||
miniMessage().toHTML(miniMessage().deserialize(server.motd)),
|
||||
);
|
||||
toast.success("Copied to clipboard.");
|
||||
}}
|
||||
>
|
||||
click to copy HTML
|
||||
</button>
|
||||
</small>
|
||||
</>
|
||||
)}
|
||||
{tab === "description" && (
|
||||
<div className="prose mt-2 break-words overflow-y-auto max-h-[175px] dark:prose-invert">
|
||||
<Markdown>{mhsfData.server?.customizationData.description}</Markdown>
|
||||
</div>
|
||||
)}
|
||||
</Material>
|
||||
);
|
||||
}
|
||||
|
||||
@ -13,69 +13,69 @@ import { DebugProvider } from "./debug/debug-provider";
|
||||
import { ReportingProvider } from "./reporting/reporting-provider";
|
||||
|
||||
export function ServerProvider({ serverId }: { serverId: string }) {
|
||||
const { server, error, loading } = useServer({ id: serverId });
|
||||
const settings = useSettingsStore();
|
||||
const mhsf = useMHSFServer(serverId);
|
||||
const { server, error, loading } = useServer({ id: serverId });
|
||||
const settings = useSettingsStore();
|
||||
const mhsf = useMHSFServer(serverId);
|
||||
|
||||
if (error !== null)
|
||||
return (
|
||||
<div className="absolute top-[50%] left-[50%]">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="Error while fetching server"
|
||||
description={
|
||||
<>
|
||||
Try again later <br /> If this occurs again, please contact
|
||||
support or make a GitHub issue. <br /> {error}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
if (error !== null)
|
||||
return (
|
||||
<div className="absolute top-[50%] left-[50%]">
|
||||
<Placeholder
|
||||
icon={<X />}
|
||||
title="Error while fetching server"
|
||||
description={
|
||||
<>
|
||||
Try again later <br /> If this occurs again, please contact
|
||||
support or make a GitHub issue. <br /> {error}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<DebugProvider
|
||||
debugOptions={{
|
||||
serverName: (server ?? { name: "" }).name,
|
||||
serverId: serverId,
|
||||
mhsfData: mhsf.server,
|
||||
serverData: server,
|
||||
onlineServerData: null,
|
||||
}}
|
||||
>
|
||||
{loading || mhsf.loading ? (
|
||||
<div className="absolute top-[50%] left-[50%] transform -translate-x-1/2 -translate-y-1/2 block justify-center text-center gap-2">
|
||||
<span className="w-full flex justify-center">
|
||||
<Spinner />
|
||||
</span>
|
||||
return (
|
||||
<DebugProvider
|
||||
debugOptions={{
|
||||
serverName: (server ?? { name: "" }).name,
|
||||
serverId: serverId,
|
||||
mhsfData: mhsf.server,
|
||||
serverData: server,
|
||||
onlineServerData: null,
|
||||
}}
|
||||
>
|
||||
{loading || mhsf.loading ? (
|
||||
<div className="absolute top-[50%] left-[50%] transform -translate-x-1/2 -translate-y-1/2 block justify-center text-center gap-2">
|
||||
<span className="w-full flex justify-center">
|
||||
<Spinner />
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<AnimatedText
|
||||
text={
|
||||
loading && mhsf.loading
|
||||
? "Loading server and MHSF data..."
|
||||
: loading
|
||||
? "Loading server data..."
|
||||
: "Loading MHSF data..."
|
||||
}
|
||||
className="text-center w-full mt-2"
|
||||
/>
|
||||
</span>
|
||||
{settings.get("debug-mode") === "true" && (
|
||||
<Button
|
||||
onClick={() => window.dispatchEvent(new Event("open-debug-menu"))}
|
||||
>
|
||||
Debug Stack
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-10">
|
||||
<ReportingProvider server={mhsf}>
|
||||
<ServerMainPage server={server as ServerResponse} mhsfData={mhsf} />
|
||||
</ReportingProvider>
|
||||
</div>
|
||||
)}
|
||||
</DebugProvider>
|
||||
);
|
||||
<span>
|
||||
<AnimatedText
|
||||
text={
|
||||
loading && mhsf.loading
|
||||
? "Loading server and MHSF data..."
|
||||
: loading
|
||||
? "Loading server data..."
|
||||
: "Loading MHSF data..."
|
||||
}
|
||||
className="text-center w-full mt-2"
|
||||
/>
|
||||
</span>
|
||||
{settings.get("debug-mode") === "true" && (
|
||||
<Button
|
||||
onClick={() => window.dispatchEvent(new Event("open-debug-menu"))}
|
||||
>
|
||||
Debug Stack
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-10">
|
||||
<ReportingProvider server={mhsf}>
|
||||
<ServerMainPage server={server as ServerResponse} mhsfData={mhsf} />
|
||||
</ReportingProvider>
|
||||
</div>
|
||||
)}
|
||||
</DebugProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -38,8 +38,8 @@ export function ServerRows({ server, mhsfData }: { server: ServerResponse, mhsfD
|
||||
const clipboard = useClipboard();
|
||||
|
||||
return (
|
||||
<span className="lg:grid lg:grid-cols-3 w-full gap-3">
|
||||
<MOTDRow server={server} />
|
||||
<span className="lg:grid lg:grid-cols-2 w-full gap-3">
|
||||
<MOTDRow server={server} mhsfData={mhsfData}/>
|
||||
<StatisticsMainRow server={server} mhsfData={mhsfData} />
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -32,7 +32,7 @@ export function StatisticsMainRow({
|
||||
|
||||
return (
|
||||
<Material
|
||||
className="relative col-span-2 h-[250px] max-lg:mt-3"
|
||||
className="relative h-[250px] max-lg:mt-3"
|
||||
padding="none"
|
||||
>
|
||||
<div className="p-4">
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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) 2025 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 { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { useUser } from "@clerk/nextjs";
|
||||
import { Editor } from "@monaco-editor/react";
|
||||
import { useEffect, useState, type ReactNode } from "react";
|
||||
|
||||
export function ClerkMetadataPopup({children}: {children: ReactNode | ReactNode[] | undefined}) {
|
||||
const [mdType, setMDType] = useState<"public" | "unsafe" | null>(null)
|
||||
const [open, setOpen] = useState(false);
|
||||
const {user} = useUser();
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("open-public-clerkmd", () => {
|
||||
setMDType("public")
|
||||
setOpen(true);
|
||||
})
|
||||
window.addEventListener("open-unsafe-clerkmd", () => {
|
||||
setMDType("unsafe")
|
||||
setOpen(true);
|
||||
})
|
||||
})
|
||||
|
||||
return <>
|
||||
{children}
|
||||
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="min-w-[850px]">
|
||||
<DialogTitle>{mdType?.toLocaleUpperCase()} metadata</DialogTitle>
|
||||
<Editor options={{domReadOnly: true, readOnly: true}} height={500} width={800} language="json" value={JSON.stringify(mdType === "public" ? user?.publicMetadata : user?.unsafeMetadata, null, 2)}/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
}
|
||||
@ -29,38 +29,77 @@
|
||||
*/
|
||||
|
||||
import { Material } from "@/components/ui/material";
|
||||
import { Setting, SettingContent, SettingDescription, SettingMeta, SettingTitle } from "./setting";
|
||||
import {
|
||||
Setting,
|
||||
SettingContent,
|
||||
SettingDescription,
|
||||
SettingMeta,
|
||||
SettingTitle,
|
||||
} from "./setting";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { AnimatedText } from "@/components/ui/animated-text";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { loadingList } from "../server-page/util";
|
||||
import { ClerkMetadataPopup } from "./clerk-metadata-popup";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Link } from "@/components/util/link";
|
||||
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
|
||||
|
||||
export function DebugSettings() {
|
||||
const [randomText, setRandomText] = useState("")
|
||||
const [randomText, setRandomText] = useState("");
|
||||
|
||||
return (
|
||||
<Material className="mt-6 grid gap-4">
|
||||
<h2 className="text-xl font-semibold text-inherit">Debug Settings</h2>
|
||||
<Setting>
|
||||
<SettingContent>
|
||||
<SettingMeta>
|
||||
<SettingTitle>
|
||||
Generate loading text
|
||||
</SettingTitle>
|
||||
<SettingDescription>
|
||||
Generate a random loading text
|
||||
</SettingDescription>
|
||||
</SettingMeta>
|
||||
<div className="block pb-6">
|
||||
<Button onClick={() => {
|
||||
setRandomText(loadingList[Math.floor(Math.random() * loadingList.length)])
|
||||
}}>
|
||||
Generate
|
||||
</Button>
|
||||
<AnimatedText className="font-bold" text={randomText + "..."}/>
|
||||
</div>
|
||||
</SettingContent>
|
||||
</Setting>
|
||||
</Material>
|
||||
);
|
||||
return (
|
||||
<Material className="mt-6 grid gap-4">
|
||||
<h2 className="text-xl font-semibold text-inherit">Debug Settings</h2>
|
||||
<Setting>
|
||||
<SettingContent>
|
||||
<SettingMeta>
|
||||
<SettingTitle>Generate loading text</SettingTitle>
|
||||
<SettingDescription>
|
||||
Generate a random loading text
|
||||
</SettingDescription>
|
||||
</SettingMeta>
|
||||
<div className="block pb-6">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setRandomText(
|
||||
loadingList[Math.floor(Math.random() * loadingList.length)],
|
||||
);
|
||||
}}
|
||||
>
|
||||
Generate
|
||||
</Button>
|
||||
<AnimatedText className="font-bold" text={randomText + "..."} />
|
||||
</div>
|
||||
</SettingContent>
|
||||
</Setting>
|
||||
<ClerkMetadataPopup>
|
||||
<Setting>
|
||||
<SettingContent>
|
||||
<SettingMeta>
|
||||
<SettingTitle>View Clerk metadata</SettingTitle>
|
||||
<SettingDescription>
|
||||
View any Clerk metadata for your user.
|
||||
</SettingDescription>
|
||||
</SettingMeta>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Button>Open metadata</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={() => window.dispatchEvent(new Event("open-public-clerkmd"))}>Public</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => window.dispatchEvent(new Event("open-unsafe-clerkmd"))}>Unsafe</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</SettingContent>
|
||||
</Setting>
|
||||
</ClerkMetadataPopup>
|
||||
</Material>
|
||||
);
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ const badgeVariants = cva(
|
||||
"purple-subtle": `bg-purple-100 dark:bg-purple-500/20 text-purple-700 dark:text-purple-400
|
||||
ring-purple-400 dark:ring-purple-500/30`,
|
||||
rainbow:
|
||||
"text-white ring-transparent [background:_linear-gradient(45deg,rgba(255,_0,_0,_1)_0%,rgba(255,_154,_0,_1)_10%,rgba(208,_222,_33,_1)_20%,rgba(79,_220,_74,_1)_30%,rgba(63,_218,_216,_1)_40%,rgba(47,_201,_226,_1)_50%,rgba(28,_127,_238,_1)_60%,rgba(95,_21,_242,_1)_70%,rgba(186,_12,_248,_1)_80%,rgba(251,_7,_217,_1)_90%,rgba(255,_0,_0,_1)_100%);] backdrop-blur-sm opacity-60 ",
|
||||
"text-white ring-transparent z-10 [background:_linear-gradient(45deg,rgba(255,_0,_0,_1)_0%,rgba(255,_154,_0,_1)_10%,rgba(208,_222,_33,_1)_20%,rgba(79,_220,_74,_1)_30%,rgba(63,_218,_216,_1)_40%,rgba(47,_201,_226,_1)_50%,rgba(28,_127,_238,_1)_60%,rgba(95,_21,_242,_1)_70%,rgba(186,_12,_248,_1)_80%,rgba(251,_7,_217,_1)_90%,rgba(255,_0,_0,_1)_100%);] backdrop-blur-sm opacity-60 ",
|
||||
custom: "",
|
||||
},
|
||||
allowIconOnly: {
|
||||
|
||||
@ -28,6 +28,8 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
"use client";
|
||||
|
||||
import { useTheme } from "@/lib/hooks/use-theme";
|
||||
import type { SVGProps } from "react";
|
||||
const Github = (props: SVGProps<SVGSVGElement>) => {
|
||||
|
||||
@ -30,11 +30,13 @@
|
||||
|
||||
import {
|
||||
ArrowDownUpIcon,
|
||||
ServerCog,
|
||||
SlidersHorizontal,
|
||||
type LucideIcon,
|
||||
} from "lucide-react";
|
||||
import type { Filter } from "../lib/types/filter";
|
||||
import { type Filter } from "../lib/types/filter";
|
||||
import type { Sort } from "../lib/types/sort";
|
||||
import { TagFilter } from "@/lib/types/filters/tag-filter";
|
||||
|
||||
type ModDBCategory = {
|
||||
displayTitle: string;
|
||||
@ -78,5 +80,18 @@ export const serverModDB: ModDBCategory[] = [
|
||||
__custom: true,
|
||||
// Entries are already pre-loaded.
|
||||
entries: []
|
||||
},
|
||||
{
|
||||
displayTitle: "Tag Filters",
|
||||
description: "These are filters that are associated with an assortment of tags.",
|
||||
entries: [
|
||||
{
|
||||
name: "Always Online",
|
||||
description: "All servers that are always online.",
|
||||
color: "#a380e0",
|
||||
value: new TagFilter(2, false),
|
||||
icon: ServerCog
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@ -36,10 +36,12 @@ import { tryCatch } from "../try-catch";
|
||||
import { transpileTypeScript } from "@/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/file/[filename]/page";
|
||||
import { useUser } from "@clerk/nextjs";
|
||||
import type { ClerkCustomActivatedModification } from "@/components/feat/server-list/modification/modification-file-creation-dialog";
|
||||
import { ClerkEmbeddedFilter } from "@/components/feat/server-list/modification/modification-action";
|
||||
import { supportedFilters } from "../types/filter";
|
||||
|
||||
type EmbeddedFilter = {
|
||||
identifier: string;
|
||||
functionFilter: (server: OnlineServer) => boolean;
|
||||
functionFilter: (server: OnlineServer) => (boolean | Promise<boolean>);
|
||||
};
|
||||
|
||||
type SortFunction<K> = (object1: K, object2: K) => number;
|
||||
@ -57,23 +59,20 @@ export function useFilters(data: OnlineServer[]) {
|
||||
const [sort, setSort] = useState<SortFunction<OnlineServer> | null>(null);
|
||||
const { user, isSignedIn } = useUser();
|
||||
|
||||
const updateServers = (newFilters: EmbeddedFilter[]) => {
|
||||
const modificationMap = data.map((v) =>
|
||||
newFilters.map((c) => c.functionFilter(v)),
|
||||
);
|
||||
const updateServers = async (newFilters: EmbeddedFilter[]) => {
|
||||
const modificationMap = await Promise.all(data.map((v) =>
|
||||
Promise.all(newFilters.map(async (c) => c.functionFilter(v))),
|
||||
));
|
||||
const resultData = data.filter(
|
||||
(_, i) => !modificationMap[i].includes(false),
|
||||
);
|
||||
const sortedData = sort === null ? resultData : resultData.sort(sort);
|
||||
|
||||
console.table({ sortedData, modificationMap, resultData, data });
|
||||
console.log({ sortedData, modificationMap, resultData, data, newFilters });
|
||||
|
||||
|
||||
if (sortedData.length !== 0)
|
||||
setFilteredData(sortedData);
|
||||
if (sortedData.length !== 0) setFilteredData(sortedData);
|
||||
};
|
||||
|
||||
// biome-ignore lint: bruh
|
||||
useEffect(() => {
|
||||
if (filteredData.length === 0 || data.length === 0) {
|
||||
window.dispatchEvent(new Event("update-modification-stack"));
|
||||
@ -129,18 +128,18 @@ export function useFilters(data: OnlineServer[]) {
|
||||
(async () =>
|
||||
type === "filter"
|
||||
? new Function(
|
||||
"server",
|
||||
`${functionBody}
|
||||
"server",
|
||||
`${functionBody}
|
||||
|
||||
return filter(server)`,
|
||||
)
|
||||
)
|
||||
: new Function(
|
||||
"serverA",
|
||||
"serverB",
|
||||
`${functionBody}
|
||||
"serverA",
|
||||
"serverB",
|
||||
`${functionBody}
|
||||
|
||||
return sort(serverA, serverB)`,
|
||||
))(),
|
||||
))(),
|
||||
);
|
||||
if (filterErr) {
|
||||
setTestModeStatus(
|
||||
@ -213,7 +212,13 @@ export function useFilters(data: OnlineServer[]) {
|
||||
if (!t)
|
||||
window.addEventListener("update-modification-stack", async () => {
|
||||
await user?.reload();
|
||||
setLoading(true);
|
||||
let newFilters: EmbeddedFilter[] = [];
|
||||
const filters =
|
||||
((isSignedIn ? user.unsafeMetadata.filters : JSON.parse(localStorage.getItem("mhsf__filters") ?? "[]")) as Array<
|
||||
ClerkEmbeddedFilter<unknown>
|
||||
>) ?? [];
|
||||
|
||||
if (isSignedIn) {
|
||||
const activatedModifications =
|
||||
(user.unsafeMetadata
|
||||
@ -232,58 +237,84 @@ export function useFilters(data: OnlineServer[]) {
|
||||
(async () =>
|
||||
c.testMode === "filter"
|
||||
? new Function(
|
||||
"server",
|
||||
`${functionBody}
|
||||
"server",
|
||||
`${functionBody}
|
||||
|
||||
return filter(server)`,
|
||||
)
|
||||
)
|
||||
: new Function(
|
||||
"serverA",
|
||||
"serverB",
|
||||
`${functionBody}
|
||||
"serverA",
|
||||
"serverB",
|
||||
`${functionBody}
|
||||
|
||||
return sort(serverA, serverB)`,
|
||||
))(),
|
||||
))(),
|
||||
);
|
||||
|
||||
if (filterErr) {
|
||||
toast.error(
|
||||
`Couldn't enable modification '${c.friendlyName}'. Please lint and test again.`,
|
||||
);
|
||||
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: () => true };
|
||||
return {
|
||||
identifier: `file-${c.originalFileName}.ts`,
|
||||
functionFilter: () => true,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof filterFunc === "function") {
|
||||
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: filterFunc };
|
||||
return {
|
||||
identifier: `file-${c.originalFileName}.ts`,
|
||||
functionFilter: filterFunc,
|
||||
};
|
||||
}
|
||||
|
||||
toast.error(
|
||||
`Couldn't enable modification '${c.friendlyName}'. Please lint and test again.`,
|
||||
);
|
||||
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: () => true };
|
||||
return {
|
||||
identifier: `file-${c.originalFileName}.ts`,
|
||||
functionFilter: () => true,
|
||||
};
|
||||
}),
|
||||
)) as EmbeddedFilter[];
|
||||
|
||||
// avoid duplicates
|
||||
// biome-ignore lint/complexity/noForEach:
|
||||
resolvedModifications.forEach((item) => {
|
||||
setFilters((c) => {
|
||||
if (c.findIndex((i) => i.identifier === item.identifier) === -1)
|
||||
return [
|
||||
...c,
|
||||
item
|
||||
]
|
||||
else return c;
|
||||
return [...c, item];
|
||||
return c;
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
newFilters = resolvedModifications.map((item) => {
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
// biome-ignore lint/complexity/noForEach:
|
||||
filters.forEach((filter) => {
|
||||
// Get back the filter type from the namespace
|
||||
const filterType = supportedFilters.find(
|
||||
(t) => filter.type === t.ns,
|
||||
);
|
||||
// Get back a filter with associated metadata
|
||||
const parsedFilter = filterType?.fi(
|
||||
filter.metadata as {
|
||||
[key: string]: string | number | boolean;
|
||||
},
|
||||
);
|
||||
|
||||
newFilters.push({
|
||||
identifier: filterType?.ns + (Math.random() * Math.random() * Math.random()).toString(),
|
||||
functionFilter: (server: OnlineServer) => parsedFilter?.applyToServer({ online: server }) ?? true
|
||||
})
|
||||
});
|
||||
|
||||
console.log(newFilters);
|
||||
|
||||
updateServers(newFilters);
|
||||
await updateServers(newFilters);
|
||||
});
|
||||
}, [data]);
|
||||
console.log(filters);
|
||||
@ -293,7 +324,9 @@ export function useFilters(data: OnlineServer[]) {
|
||||
testModeEnabled,
|
||||
testModeLoading,
|
||||
testModeStatus,
|
||||
filterCount: filters.filter((item, index, array) => array.indexOf(item) === index).length + (sort === null ? 1 : 0),
|
||||
filterCount:
|
||||
filters.filter((item, index, array) => array.indexOf(item) === index)
|
||||
.length + (sort === null ? 1 : 0),
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
||||
44
apps/www/src/lib/hooks/use-modifications-change.tsx
Normal file
44
apps/www/src/lib/hooks/use-modifications-change.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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) 2025 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 { allTags } from "@/config/tags"
|
||||
import { useUser } from "@clerk/nextjs"
|
||||
|
||||
export function useModificationsChange() {
|
||||
const {isSignedIn} = useUser()
|
||||
|
||||
return {
|
||||
addFilterData: async (namespace: string, identifier: { [key: string]: string | number | boolean }) => {
|
||||
if (isSignedIn) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,3 +74,24 @@ export function useSettingsStore() {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// An exact copy of the API without Clerk
|
||||
export function useNoClerkSettingsStore() {
|
||||
return {
|
||||
get: (key: string) => {
|
||||
if (localStorage.getItem(key) === "true")
|
||||
return true;
|
||||
if (localStorage.getItem(key) === "false")
|
||||
return false;
|
||||
return localStorage.getItem(key);
|
||||
},
|
||||
set: async (
|
||||
key: string,
|
||||
value: string | boolean,
|
||||
userEntry: boolean,
|
||||
__unsafeMetadata = false
|
||||
) => {
|
||||
localStorage.setItem(key, value.toString());
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -28,10 +28,39 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import type { OnlineServer } from "./mh-server";
|
||||
import { allTags } from "@/config/tags";
|
||||
import type { OnlineServer, ServerResponse } from "./mh-server";
|
||||
import type { MHSFData } from "./data";
|
||||
import { TagFilter } from "./filters/tag-filter";
|
||||
import { CategoryFilter } from "./filters/category-filter";
|
||||
|
||||
/* Any filter that can be converted back and forth from a string or a Filter object */
|
||||
export interface Filter {
|
||||
toIdentifier(): string;
|
||||
fromIdentifier(identifier: string): Filter;
|
||||
applyToServer(server: OnlineServer): boolean;
|
||||
}
|
||||
type(): "filter";
|
||||
toIdentifier(): { [key: string]: string | number | boolean };
|
||||
getSpecificFilterId(): string;
|
||||
fromIdentifier(identifier: {
|
||||
[key: string]: string | number | boolean;
|
||||
}): Filter;
|
||||
applyToServer(server: {
|
||||
online?: OnlineServer;
|
||||
server?: ServerResponse;
|
||||
mhsfData?: MHSFData;
|
||||
}): Promise<boolean>;
|
||||
}
|
||||
|
||||
export const supportedFilters: {
|
||||
ns: string;
|
||||
fi: (identifier: {
|
||||
[key: string]: string | number | boolean;
|
||||
}) => Filter;
|
||||
}[] = [
|
||||
{
|
||||
ns: "app.mhsf.filter.tagFilter",
|
||||
fi: new TagFilter(0, false).fromIdentifier
|
||||
},
|
||||
{
|
||||
ns: "app.mhsf.filter.categoryFilter",
|
||||
fi: new CategoryFilter(0).fromIdentifier
|
||||
}
|
||||
];
|
||||
|
||||
64
apps/www/src/lib/types/filters/category-filter.ts
Normal file
64
apps/www/src/lib/types/filters/category-filter.ts
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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) 2025 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 { allCategories } from "@/config/tags";
|
||||
import type { MHSFData } from "../data";
|
||||
import type { Filter } from "../filter";
|
||||
import type { OnlineServer, ServerResponse } from "../mh-server";
|
||||
|
||||
export class CategoryFilter implements Filter {
|
||||
categoryIndex: number;
|
||||
|
||||
type(): "filter" {
|
||||
return "filter";
|
||||
}
|
||||
|
||||
toIdentifier(): { [key: string]: string | number | boolean } {
|
||||
return { categoryIndex: this.categoryIndex };
|
||||
}
|
||||
|
||||
fromIdentifier(identifier: { [key: string]: string | number | boolean; }): Filter {
|
||||
return new CategoryFilter(identifier.categoryIndex as number);
|
||||
}
|
||||
|
||||
getSpecificFilterId(): string {
|
||||
return "app.mhsf.filter.categoryFilter";
|
||||
}
|
||||
|
||||
applyToServer(server: { online?: OnlineServer; server?: ServerResponse; mhsfData?: MHSFData; }): Promise<boolean> {
|
||||
if (server.online !== undefined)
|
||||
return allCategories[this.categoryIndex].condition(server.online);
|
||||
return new Promise((r) => r(true));
|
||||
}
|
||||
|
||||
constructor(categoryIndex: number) {
|
||||
this.categoryIndex = categoryIndex;
|
||||
}
|
||||
}
|
||||
90
apps/www/src/lib/types/filters/tag-filter.ts
Normal file
90
apps/www/src/lib/types/filters/tag-filter.ts
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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) 2025 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 { allTags } from "@/config/tags";
|
||||
import type { MHSFData } from "../data";
|
||||
import type { OnlineServer, ServerResponse } from "../mh-server";
|
||||
import type { Filter } from "../filter";
|
||||
|
||||
export class TagFilter implements Filter {
|
||||
tagId: string;
|
||||
opposite: boolean;
|
||||
|
||||
type(): "filter" {
|
||||
return "filter";
|
||||
}
|
||||
|
||||
toIdentifier(): { [key: string]: string | number | boolean } {
|
||||
return { tagId: this.tagId, opposite: this.opposite };
|
||||
}
|
||||
|
||||
getSpecificFilterId(): string {
|
||||
return "app.mhsf.filter.tagFilter";
|
||||
}
|
||||
|
||||
fromIdentifier(identifier: {
|
||||
[key: string]: string | number | boolean;
|
||||
}): Filter {
|
||||
return new TagFilter(identifier.tagId as string, identifier.opposite as boolean);
|
||||
}
|
||||
|
||||
constructor(tagIndex: number | string, opposite: boolean) {
|
||||
if (typeof tagIndex === "string") this.tagId = tagIndex;
|
||||
else this.tagId = btoa(allTags[tagIndex].docsName);
|
||||
this.opposite = opposite;
|
||||
}
|
||||
|
||||
applyToServer(server: {
|
||||
online?: OnlineServer;
|
||||
server?: ServerResponse;
|
||||
mhsfData?: MHSFData;
|
||||
}): Promise<boolean> {
|
||||
const result = (
|
||||
(
|
||||
allTags.find((c) => btoa(c.docsName) === this.tagId) ?? {
|
||||
condition: () => true,
|
||||
}
|
||||
).condition ?? (() => true)
|
||||
)(server);
|
||||
|
||||
console.log(result, server.online?.name, (
|
||||
allTags.find((c) => btoa(c.docsName) === this.tagId) ?? {
|
||||
condition: () => true,
|
||||
}
|
||||
));
|
||||
|
||||
if (typeof result === "boolean")
|
||||
return new Promise((r) => r(this.opposite ? !result : result))
|
||||
|
||||
return new Promise((r) => {
|
||||
result.then((c) => r(this.opposite ? !c : c))
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -31,7 +31,11 @@
|
||||
import type { OnlineServer } from "./mh-server";
|
||||
|
||||
export interface Sort {
|
||||
toIdentifier(): string;
|
||||
fromIdentifier(identifier: string): Sort;
|
||||
type(): "sort";
|
||||
toIdentifier(): { [key: string]: string | number | boolean };
|
||||
getSpecificSortId(): string;
|
||||
fromIdentifier(identifier: {
|
||||
[key: string]: string | number | boolean;
|
||||
}): Sort;
|
||||
sortToServers(serverA: OnlineServer, serverB: OnlineServer): number;
|
||||
}
|
||||
@ -49,6 +49,8 @@ export default process.env.NEXT_PUBLIC_IS_AUTH === "true"
|
||||
? clerkMiddleware(async (auth, req) => {
|
||||
const authRes = await auth();
|
||||
const client = await clerkClient();
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
requestHeaders.set("x-url", req.url);
|
||||
|
||||
if (isRootRoute(req)) {
|
||||
switch (authRes.userId === null) {
|
||||
@ -70,6 +72,12 @@ export default process.env.NEXT_PUBLIC_IS_AUTH === "true"
|
||||
new URL(`/server/v2/minehut/${minehutRes.server._id}`, req.url),
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
headers: requestHeaders,
|
||||
},
|
||||
});
|
||||
})
|
||||
: (request: NextRequest) => {};
|
||||
|
||||
|
||||
@ -45,8 +45,6 @@ export default async function handler(
|
||||
const result = await betterStackResult.json();
|
||||
const url = await betterStackURL.json();
|
||||
|
||||
console.log(result)
|
||||
|
||||
const filtered = result.data.filter(
|
||||
(c: any) =>
|
||||
c.attributes.ends_at === null &&
|
||||
|
||||
@ -57,7 +57,7 @@ export default async function handler(
|
||||
return res.status(401).json({ error: "Unauthorized" });
|
||||
}
|
||||
if (
|
||||
(await (await clerkClient()).users.getUser(userId)).publicMetadata.player ==
|
||||
(await (await clerkClient()).users.getUser(userId)).publicMetadata.player ===
|
||||
undefined
|
||||
) {
|
||||
return res.status(401).json({ error: "Account not linked" });
|
||||
@ -68,7 +68,7 @@ export default async function handler(
|
||||
const db = client.db(process.env.CUSTOM_MONGO_DB ?? "mhsf");
|
||||
const collection = db.collection("owned-servers");
|
||||
|
||||
if ((await collection.findOne({ server: server })) == undefined) {
|
||||
if ((await collection.findOne({ server: server })) === undefined) {
|
||||
const mh = await fetch(
|
||||
process.env.MHSF_BACKEND_API_LOCATION ??
|
||||
"https://api.minehut.com/servers",
|
||||
@ -116,7 +116,7 @@ export default async function handler(
|
||||
.send({ message: "The linked account doesn't own the server." });
|
||||
}
|
||||
}
|
||||
if (i == servers.length) {
|
||||
if (i === servers.length) {
|
||||
// Close the database, but don't close this
|
||||
// serverless instance until it happens
|
||||
waitUntil(client.close());
|
||||
|
||||
285
yarn.lock
285
yarn.lock
@ -1059,6 +1059,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-darwin-arm64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz#e79a4756bea9a06a7aadb4391ee53cb154a4968c"
|
||||
integrity sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-darwin-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61"
|
||||
@ -1066,46 +1073,98 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-darwin-x64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz#f1f1d386719f6933796415d84937502b7199a744"
|
||||
integrity sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz#447c5026700c01a993c7804eb8af5f6e9868c07f"
|
||||
integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz#843f7c09c7245dc0d3cfec2b3c83bb08799a704f"
|
||||
integrity sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==
|
||||
|
||||
"@img/sharp-libvips-darwin-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062"
|
||||
integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==
|
||||
|
||||
"@img/sharp-libvips-darwin-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz#1239c24426c06a8e833815562f78047a3bfbaaf8"
|
||||
integrity sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==
|
||||
|
||||
"@img/sharp-libvips-linux-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704"
|
||||
integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==
|
||||
|
||||
"@img/sharp-libvips-linux-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz#20d276cefd903ee483f0441ba35961679c286315"
|
||||
integrity sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==
|
||||
|
||||
"@img/sharp-libvips-linux-arm@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197"
|
||||
integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==
|
||||
|
||||
"@img/sharp-libvips-linux-arm@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz#067c0b566eae8063738cf1b1db8f8a8573b5465c"
|
||||
integrity sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==
|
||||
|
||||
"@img/sharp-libvips-linux-ppc64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz#682334595f2ca00e0a07a675ba170af165162802"
|
||||
integrity sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==
|
||||
|
||||
"@img/sharp-libvips-linux-s390x@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce"
|
||||
integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==
|
||||
|
||||
"@img/sharp-libvips-linux-s390x@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz#82fcd68444b3666384235279c145c2b28d8ee302"
|
||||
integrity sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==
|
||||
|
||||
"@img/sharp-libvips-linux-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0"
|
||||
integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==
|
||||
|
||||
"@img/sharp-libvips-linux-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz#65b2b908bf47156b0724fde9095676c83a18cf5a"
|
||||
integrity sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5"
|
||||
integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz#72accf924e80b081c8db83b900b444a67c203f01"
|
||||
integrity sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff"
|
||||
integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz#1fa052737e203f46bf44192acd01f9faf11522d7"
|
||||
integrity sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==
|
||||
|
||||
"@img/sharp-linux-arm64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22"
|
||||
@ -1113,6 +1172,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-linux-arm64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz#c36ef964499b8cfc2d2ed88fe68f27ce41522c80"
|
||||
integrity sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-arm@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff"
|
||||
@ -1120,6 +1186,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm" "1.0.5"
|
||||
|
||||
"@img/sharp-linux-arm@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz#c96e38ff028d645912bb0aa132a7178b96997866"
|
||||
integrity sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-s390x@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667"
|
||||
@ -1127,6 +1200,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-s390x" "1.0.4"
|
||||
|
||||
"@img/sharp-linux-s390x@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz#8ac58d9a49dcb08215e76c8d450717979b7815c3"
|
||||
integrity sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-s390x" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb"
|
||||
@ -1134,6 +1214,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-linux-x64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz#3d8652efac635f0dba39d5e3b8b49515a2b2dee1"
|
||||
integrity sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-linuxmusl-arm64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b"
|
||||
@ -1141,6 +1228,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-linuxmusl-arm64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz#b267e6a3e06f9e4d345cde471e5480c5c39e6969"
|
||||
integrity sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-linuxmusl-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48"
|
||||
@ -1148,6 +1242,13 @@
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-linuxmusl-x64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz#a8dee4b6227f348c4bbacaa6ac3dc584a1a80391"
|
||||
integrity sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-wasm32@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1"
|
||||
@ -1155,16 +1256,33 @@
|
||||
dependencies:
|
||||
"@emnapi/runtime" "^1.2.0"
|
||||
|
||||
"@img/sharp-wasm32@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz#f7dfd66b6c231269042d3d8750c90f28b9ddcba1"
|
||||
integrity sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==
|
||||
dependencies:
|
||||
"@emnapi/runtime" "^1.4.0"
|
||||
|
||||
"@img/sharp-win32-ia32@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9"
|
||||
integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==
|
||||
|
||||
"@img/sharp-win32-ia32@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz#4bc293705df76a5f0a02df66ca3dc12e88f61332"
|
||||
integrity sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==
|
||||
|
||||
"@img/sharp-win32-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342"
|
||||
integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==
|
||||
|
||||
"@img/sharp-win32-x64@0.34.1":
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz#8a7922fec949f037c204c79f6b83238d2482384b"
|
||||
integrity sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==
|
||||
|
||||
"@inngest/ai@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@inngest/ai/-/ai-0.1.3.tgz#25a86d08a8fe7288fdcde1bb02ad084ed3fa2166"
|
||||
@ -1688,10 +1806,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.1.6.tgz#2fa863d8c568a56b1c8328a86e621b8bdd4f2a20"
|
||||
integrity sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==
|
||||
|
||||
"@next/env@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.2.0.tgz#4c3508ca2c0bb2bc324066818bb8d0415f767641"
|
||||
integrity sha512-eMgJu1RBXxxqqnuRJQh5RozhskoNUDHBFybvi+Z+yK9qzKeG7dadhv/Vp1YooSZmCnegf7JxWuapV77necLZNA==
|
||||
"@next/env@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.3.1.tgz#fca98dcb90d92d555972cdbf03adf9aa982e2115"
|
||||
integrity sha512-cwK27QdzrMblHSn9DZRV+DQscHXRuJv6MydlJRpFSqJWZrTYMLzKDeyueJNN9MGd8NNiUKzDQADAf+dMLXX7YQ==
|
||||
|
||||
"@next/env@^13.4.3":
|
||||
version "13.5.11"
|
||||
@ -1717,80 +1835,80 @@
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.6.tgz#92f99badab6cb41f4c5c11a3feffa574bd6a9276"
|
||||
integrity sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==
|
||||
|
||||
"@next/swc-darwin-arm64@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.0.tgz#51ebba2162330ee3e8b3412bf31defd94a7b85e7"
|
||||
integrity sha512-rlp22GZwNJjFCyL7h5wz9vtpBVuCt3ZYjFWpEPBGzG712/uL1bbSkS675rVAUCRZ4hjoTJ26Q7IKhr5DfJrHDA==
|
||||
"@next/swc-darwin-arm64@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.1.tgz#8f9589aed9f6816687440aa36a86376b3a16af58"
|
||||
integrity sha512-hjDw4f4/nla+6wysBL07z52Gs55Gttp5Bsk5/8AncQLJoisvTBP0pRIBK/B16/KqQyH+uN4Ww8KkcAqJODYH3w==
|
||||
|
||||
"@next/swc-darwin-x64@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.6.tgz#f56f4f8d5f6cb5d3915912ac95590d387f897da5"
|
||||
integrity sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==
|
||||
|
||||
"@next/swc-darwin-x64@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.0.tgz#90fd6c6cee494d4348342434cfb9ca9506eae895"
|
||||
integrity sha512-DiU85EqSHogCz80+sgsx90/ecygfCSGl5P3b4XDRVZpgujBm5lp4ts7YaHru7eVTyZMjHInzKr+w0/7+qDrvMA==
|
||||
"@next/swc-darwin-x64@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.1.tgz#2df013226d848394ed7307188c141f0e6da4ab3e"
|
||||
integrity sha512-q+aw+cJ2ooVYdCEqZVk+T4Ni10jF6Fo5DfpEV51OupMaV5XL6pf3GCzrk6kSSZBsMKZtVC1Zm/xaNBFpA6bJ2g==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.6.tgz#0aaffae519c93d1006419d7b98c34ebfd80ecacd"
|
||||
integrity sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.0.tgz#f10a26cdbacf2e3de2a02a926c72857b3cb613e1"
|
||||
integrity sha512-VnpoMaGukiNWVxeqKHwi8MN47yKGyki5q+7ql/7p/3ifuU2341i/gDwGK1rivk0pVYbdv5D8z63uu9yMw0QhpQ==
|
||||
"@next/swc-linux-arm64-gnu@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.1.tgz#d1c4e24b2b27c36a7ebc21ae0573e9e98f794143"
|
||||
integrity sha512-wBQ+jGUI3N0QZyWmmvRHjXjTWFy8o+zPFLSOyAyGFI94oJi+kK/LIZFJXeykvgXUk1NLDAEFDZw/NVINhdk9FQ==
|
||||
|
||||
"@next/swc-linux-arm64-musl@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.6.tgz#e7398d3d31ca60033f708a718cd6c31edcee2e9a"
|
||||
integrity sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==
|
||||
|
||||
"@next/swc-linux-arm64-musl@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.0.tgz#1821c9a1dd17c441d8182f5cefd586f7902fcdb5"
|
||||
integrity sha512-ka97/ssYE5nPH4Qs+8bd8RlYeNeUVBhcnsNUmFM6VWEob4jfN9FTr0NBhXVi1XEJpj3cMfgSRW+LdE3SUZbPrw==
|
||||
"@next/swc-linux-arm64-musl@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.1.tgz#bce27533f9f046800f850a9c20832e8c15b10955"
|
||||
integrity sha512-IIxXEXRti/AulO9lWRHiCpUUR8AR/ZYLPALgiIg/9ENzMzLn3l0NSxVdva7R/VDcuSEBo0eGVCe3evSIHNz0Hg==
|
||||
|
||||
"@next/swc-linux-x64-gnu@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.6.tgz#d76c72508f4d79d6016cab0c52640b93e590cffb"
|
||||
integrity sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==
|
||||
|
||||
"@next/swc-linux-x64-gnu@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.0.tgz#522f55c7672346bab43bce0bcb35c4cb668ad20f"
|
||||
integrity sha512-zY1JduE4B3q0k2ZCE+DAF/1efjTXUsKP+VXRtrt/rJCTgDlUyyryx7aOgYXNc1d8gobys/Lof9P9ze8IyRDn7Q==
|
||||
"@next/swc-linux-x64-gnu@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.1.tgz#f90558d93bc25e01b0b271725e291863286753c4"
|
||||
integrity sha512-bfI4AMhySJbyXQIKH5rmLJ5/BP7bPwuxauTvVEiJ/ADoddaA9fgyNNCcsbu9SlqfHDoZmfI6g2EjzLwbsVTr5A==
|
||||
|
||||
"@next/swc-linux-x64-musl@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.6.tgz#0b8ba80a53e65bf8970ed11ea923001e2512c7cb"
|
||||
integrity sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==
|
||||
|
||||
"@next/swc-linux-x64-musl@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.0.tgz#e23be1d046c9a630a0315588f9d692d9705ac355"
|
||||
integrity sha512-QqvLZpurBD46RhaVaVBepkVQzh8xtlUN00RlG4Iq1sBheNugamUNPuZEH1r9X1YGQo1KqAe1iiShF0acva3jHQ==
|
||||
"@next/swc-linux-x64-musl@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.1.tgz#639f143bd0f3fd6e1bde4b383dc6cd8a8ff12628"
|
||||
integrity sha512-FeAbR7FYMWR+Z+M5iSGytVryKHiAsc0x3Nc3J+FD5NVbD5Mqz7fTSy8CYliXinn7T26nDMbpExRUI/4ekTvoiA==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.6.tgz#81b5dbbfdada2c05deef688e799af4a24097b65f"
|
||||
integrity sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.0.tgz#9e2cb008b82c676dad7d632a43549f969cb2194f"
|
||||
integrity sha512-ODZ0r9WMyylTHAN6pLtvUtQlGXBL9voljv6ujSlcsjOxhtXPI1Ag6AhZK0SE8hEpR1374WZZ5w33ChpJd5fsjw==
|
||||
"@next/swc-win32-arm64-msvc@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.1.tgz#52ee1e63b192fec8f0230caf839cfc308d0d44d1"
|
||||
integrity sha512-yP7FueWjphQEPpJQ2oKmshk/ppOt+0/bB8JC8svPUZNy0Pi3KbPx2Llkzv1p8CoQa+D2wknINlJpHf3vtChVBw==
|
||||
|
||||
"@next/swc-win32-x64-msvc@15.1.6":
|
||||
version "15.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.6.tgz#131993c45ffd124fb4b15258e2f3f9669c143e3c"
|
||||
integrity sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==
|
||||
|
||||
"@next/swc-win32-x64-msvc@15.2.0":
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.0.tgz#d280f450a5b6dbb7437c3265f81ea62febf4bf3c"
|
||||
integrity sha512-8+4Z3Z7xa13NdUuUAcpVNA6o76lNPniBd9Xbo02bwXQXnZgFvEopwY2at5+z7yHl47X9qbZpvwatZ2BRo3EdZw==
|
||||
"@next/swc-win32-x64-msvc@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.1.tgz#df5ceb9c3b97bf0d61cb6e84f79bbf9e91a89d29"
|
||||
integrity sha512-3PMvF2zRJAifcRNni9uMk/gulWfWS+qVI/pagd+4yLF5bcXPZPPH2xlYRYOsUjmCJOXSTAC2PjRzbhsRzR2fDQ==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
@ -3915,10 +4033,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
|
||||
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
||||
|
||||
"@types/react-dom@^19", "@types/react-dom@^19.0.3":
|
||||
version "19.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f"
|
||||
integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==
|
||||
"@types/react-dom@19.0.4", "@types/react-dom@^19":
|
||||
version "19.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89"
|
||||
integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==
|
||||
|
||||
"@types/react-twemoji@^0.4.3":
|
||||
version "0.4.3"
|
||||
@ -3927,10 +4045,10 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^19", "@types/react@^19.0.8":
|
||||
version "19.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.2.tgz#11df86f66f188f212c90ecb537327ec68bfd593f"
|
||||
integrity sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==
|
||||
"@types/react@*", "@types/react@19.0.10", "@types/react@^19":
|
||||
version "19.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.10.tgz#d0c66dafd862474190fe95ce11a68de69ed2b0eb"
|
||||
integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==
|
||||
dependencies:
|
||||
csstype "^3.0.2"
|
||||
|
||||
@ -10221,12 +10339,12 @@ next@15.1.6:
|
||||
"@next/swc-win32-x64-msvc" "15.1.6"
|
||||
sharp "^0.33.5"
|
||||
|
||||
next@15.2.0:
|
||||
version "15.2.0"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-15.2.0.tgz#00f4619ae4322102b08c1a8bf315f7b757525508"
|
||||
integrity sha512-VaiM7sZYX8KIAHBrRGSFytKknkrexNfGb8GlG6e93JqueCspuGte8i4ybn8z4ww1x3f2uzY4YpTaBEW4/hvsoQ==
|
||||
next@^15.3.1:
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-15.3.1.tgz#69cf2c124e504db64e14fc75eb29bd64c0c787a7"
|
||||
integrity sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==
|
||||
dependencies:
|
||||
"@next/env" "15.2.0"
|
||||
"@next/env" "15.3.1"
|
||||
"@swc/counter" "0.1.3"
|
||||
"@swc/helpers" "0.5.15"
|
||||
busboy "1.6.0"
|
||||
@ -10234,15 +10352,15 @@ next@15.2.0:
|
||||
postcss "8.4.31"
|
||||
styled-jsx "5.1.6"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "15.2.0"
|
||||
"@next/swc-darwin-x64" "15.2.0"
|
||||
"@next/swc-linux-arm64-gnu" "15.2.0"
|
||||
"@next/swc-linux-arm64-musl" "15.2.0"
|
||||
"@next/swc-linux-x64-gnu" "15.2.0"
|
||||
"@next/swc-linux-x64-musl" "15.2.0"
|
||||
"@next/swc-win32-arm64-msvc" "15.2.0"
|
||||
"@next/swc-win32-x64-msvc" "15.2.0"
|
||||
sharp "^0.33.5"
|
||||
"@next/swc-darwin-arm64" "15.3.1"
|
||||
"@next/swc-darwin-x64" "15.3.1"
|
||||
"@next/swc-linux-arm64-gnu" "15.3.1"
|
||||
"@next/swc-linux-arm64-musl" "15.3.1"
|
||||
"@next/swc-linux-x64-gnu" "15.3.1"
|
||||
"@next/swc-linux-x64-musl" "15.3.1"
|
||||
"@next/swc-win32-arm64-msvc" "15.3.1"
|
||||
"@next/swc-win32-x64-msvc" "15.3.1"
|
||||
sharp "^0.34.1"
|
||||
|
||||
nextjs-toploader@^1.6.12:
|
||||
version "1.6.12"
|
||||
@ -11042,14 +11160,7 @@ react-day-picker@8.10.1:
|
||||
resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-8.10.1.tgz#4762ec298865919b93ec09ba69621580835b8e80"
|
||||
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
||||
|
||||
react-dom@19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57"
|
||||
integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==
|
||||
dependencies:
|
||||
scheduler "^0.25.0"
|
||||
|
||||
react-dom@^19.0.0:
|
||||
react-dom@^19.0.0, react-dom@^19.1.0:
|
||||
version "19.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623"
|
||||
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
|
||||
@ -11222,12 +11333,7 @@ react-transition-group@^4.4.5:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react@19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd"
|
||||
integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==
|
||||
|
||||
react@^19.0.0:
|
||||
react@^19.0.0, react@^19.1.0:
|
||||
version "19.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
|
||||
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
|
||||
@ -11808,11 +11914,6 @@ sax@>=0.6.0:
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
|
||||
integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
|
||||
|
||||
scheduler@^0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015"
|
||||
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
|
||||
|
||||
scheduler@^0.26.0:
|
||||
version "0.26.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337"
|
||||
@ -11947,6 +12048,36 @@ sharp@^0.33.1, sharp@^0.33.5:
|
||||
"@img/sharp-win32-ia32" "0.33.5"
|
||||
"@img/sharp-win32-x64" "0.33.5"
|
||||
|
||||
sharp@^0.34.1:
|
||||
version "0.34.1"
|
||||
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.1.tgz#e5922894b0cc7ddf159eeabc6d5668e4e8b11d61"
|
||||
integrity sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==
|
||||
dependencies:
|
||||
color "^4.2.3"
|
||||
detect-libc "^2.0.3"
|
||||
semver "^7.7.1"
|
||||
optionalDependencies:
|
||||
"@img/sharp-darwin-arm64" "0.34.1"
|
||||
"@img/sharp-darwin-x64" "0.34.1"
|
||||
"@img/sharp-libvips-darwin-arm64" "1.1.0"
|
||||
"@img/sharp-libvips-darwin-x64" "1.1.0"
|
||||
"@img/sharp-libvips-linux-arm" "1.1.0"
|
||||
"@img/sharp-libvips-linux-arm64" "1.1.0"
|
||||
"@img/sharp-libvips-linux-ppc64" "1.1.0"
|
||||
"@img/sharp-libvips-linux-s390x" "1.1.0"
|
||||
"@img/sharp-libvips-linux-x64" "1.1.0"
|
||||
"@img/sharp-libvips-linuxmusl-arm64" "1.1.0"
|
||||
"@img/sharp-libvips-linuxmusl-x64" "1.1.0"
|
||||
"@img/sharp-linux-arm" "0.34.1"
|
||||
"@img/sharp-linux-arm64" "0.34.1"
|
||||
"@img/sharp-linux-s390x" "0.34.1"
|
||||
"@img/sharp-linux-x64" "0.34.1"
|
||||
"@img/sharp-linuxmusl-arm64" "0.34.1"
|
||||
"@img/sharp-linuxmusl-x64" "0.34.1"
|
||||
"@img/sharp-wasm32" "0.34.1"
|
||||
"@img/sharp-win32-ia32" "0.34.1"
|
||||
"@img/sharp-win32-x64" "0.34.1"
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user