diff --git a/apps/www/src/app/(dashboard)/dashboard/layout.tsx b/apps/www/src/app/(dashboard)/dashboard/layout.tsx
deleted file mode 100644
index 11b6ce9..0000000
--- a/apps/www/src/app/(dashboard)/dashboard/layout.tsx
+++ /dev/null
@@ -1,135 +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 (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Acme Inc
-
-
- Enterprise
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- a
-
-
-
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/apps/www/src/app/(main)/layout.tsx b/apps/www/src/app/(main)/layout.tsx
index 37e5b73..8975969 100644
--- a/apps/www/src/app/(main)/layout.tsx
+++ b/apps/www/src/app/(main)/layout.tsx
@@ -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,8 +44,6 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
- const searchParams = useSearchParams();
- const search = searchParams?.get("theme") || "light";
return (
<>
diff --git a/apps/www/src/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/category/[category]/modification/custom/[custom-mod]/page.tsx b/apps/www/src/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/category/[category]/modification/custom/[custom-mod]/page.tsx
index 03b31f7..612c050 100644
--- a/apps/www/src/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/category/[category]/modification/custom/[custom-mod]/page.tsx
+++ b/apps/www/src/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/category/[category]/modification/custom/[custom-mod]/page.tsx
@@ -134,6 +134,7 @@ export default function ModificationPage({
activatedModifications: modificationArray
}
});
+ communicator.send("rerender-servers", {});
}}>
{modObj?.active ? "Disable" : "Enable"}
@@ -165,6 +166,7 @@ export default function ModificationPage({
});
toast.success(`Deleted in ${Date.now() - time}ms`);
router.push(backRoute);
+ communicator.send("rerender-servers", {});
}}
>
Delete
diff --git a/apps/www/src/components/feat/effects/bento-grid.tsx b/apps/www/src/components/feat/effects/bento-grid.tsx
deleted file mode 100644
index 81a62fb..0000000
--- a/apps/www/src/components/feat/effects/bento-grid.tsx
+++ /dev/null
@@ -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 (
-
- {children}
-
- );
-};
-
-const BentoCard = ({
- name,
- className,
- background,
- Icon,
- description,
- href,
- cta,
- ...props
-}: BentoCardProps) => (
-
-
{background}
-
-
-
- {name}
-
-
{description}
-
-
-
-
-);
-
-export { BentoCard, BentoGrid };
diff --git a/apps/www/src/components/feat/footer/footer.tsx b/apps/www/src/components/feat/footer/footer.tsx
index a21fd32..ad126be 100644
--- a/apps/www/src/components/feat/footer/footer.tsx
+++ b/apps/www/src/components/feat/footer/footer.tsx
@@ -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 (
@@ -50,7 +52,7 @@ export function Footer() {
-
+
diff --git a/apps/www/src/components/feat/home-page/font-changer.tsx b/apps/www/src/components/feat/home-page/font-changer.tsx
index bcd42fb..584548b 100644
--- a/apps/www/src/components/feat/home-page/font-changer.tsx
+++ b/apps/www/src/components/feat/home-page/font-changer.tsx
@@ -90,8 +90,6 @@ export function FontChanger({
return () => clearInterval(interval);
}, []);
- console.log(position);
-
return (
-
-
-
-
-
-
- MHSF
-
- v{version}
-
-
-
-
-
- Platform
-
-
-
- Go to Dynamic Home Page
-
-
-
+ return (
+
+
+
+
+
+
+
+ MHSF
+
+ v{version}
+
+
+
+
+
+ Platform
+
+
+
+ Go to Dynamic Home Page
+
+
+
-
-
-
- Go to Home Page
-
-
-
-
+
+
+
+ Go to Home Page
+
+
+
+
- {
- clipboard.writeText(brandingIconClipboard);
- toast.success("Copied icon to clipboard!");
- }}
- >
-
- Copy Logo as SVG
-
-
-
-
-
-
- Open GitHub
-
-
-
-
-
-
- Open GitHub Releases
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ Copy Logo as SVG
+
+
+
+
+
+
+ Open GitHub
+
+
+
+
+
+
+ Open GitHub Releases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
- );
+ style={{ borderRadius: "inherit" }}
+ >
+
+
+
+
+
+ );
}
diff --git a/apps/www/src/components/feat/server-list/modification/modification-action.tsx b/apps/www/src/components/feat/server-list/modification/modification-action.tsx
index 674d852..9519a60 100644
--- a/apps/www/src/components/feat/server-list/modification/modification-action.tsx
+++ b/apps/www/src/components/feat/server-list/modification/modification-action.tsx
@@ -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 = {
+ type: string;
+ metadata: T;
+};
+
export function ModificationAction({ value }: { value?: Action }) {
- return (
- <>
- {value !== undefined && "customAction" in value ? (
-
-
- {value.customAction === "custom-sort"
- ? "Create Sort"
- : "Create Filter"}
-
-
- ) : (
- Apply
- )}
- >
- );
+ const { isSignedIn, user } = useUser();
+ const [applied, setApplied] = useState();
+ 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
+ >) ?? []
+ ).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
+ >) ?? []
+ ).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 ? (
+
+
+ {value.customAction === "custom-sort"
+ ? "Create Sort"
+ : "Create Filter"}
+
+
+ ) : (
+ {
+ if (value?.type() === "filter") {
+ const filter = value as Filter;
+ const existing = findExisting();
+
+ if (isSignedIn) {
+ const existingArray =
+ (user.unsafeMetadata.filters as Array<
+ ClerkEmbeddedFilter
+ >) ?? [];
+ 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
+ >) ?? []),
+ ] as Array>,
+ },
+ });
+ else
+ await user.update({
+ unsafeMetadata: {
+ filters: existingArray,
+ ...user.unsafeMetadata,
+ },
+ });
+ } else {
+ const existingArray =
+ (JSON.parse(
+ localStorage.getItem("mhsf__filters") ?? "[]",
+ ) as Array>) ?? [];
+ 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>) ?? []),
+ ]),
+ );
+ else
+ localStorage.setItem("mhsf__filters", JSON.stringify(existingArray));
+ }
+
+ setApplied(findExisting());
+ }
+ communication.fromIframe.send("rerender-servers", {});
+ }}
+ >
+ {applied === -1 ? "A" : "Una"}pply
+
+ )}
+ >
+ );
}
diff --git a/apps/www/src/components/feat/server-list/modification/modification-frame.tsx b/apps/www/src/components/feat/server-list/modification/modification-frame.tsx
index d1d6640..092bdf8 100644
--- a/apps/www/src/components/feat/server-list/modification/modification-frame.tsx
+++ b/apps/www/src/components/feat/server-list/modification/modification-frame.tsx
@@ -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
diff --git a/apps/www/src/components/feat/server-page/motd/motd-row.tsx b/apps/www/src/components/feat/server-page/motd/motd-row.tsx
index f141cee..47dcc20 100644
--- a/apps/www/src/components/feat/server-page/motd/motd-row.tsx
+++ b/apps/www/src/components/feat/server-page/motd/motd-row.tsx
@@ -89,28 +89,6 @@ export function MOTDRow({
)}
-
-
-
-
- window.dispatchEvent(new Event("open-rearrange-menu"))
- }
- >
- Rearrange server items
-
-
-
-
-
-
-
-
{tab === "motd" && (
diff --git a/apps/www/src/components/feat/settings/clerk-metadata-popup.tsx b/apps/www/src/components/feat/settings/clerk-metadata-popup.tsx
new file mode 100644
index 0000000..c637857
--- /dev/null
+++ b/apps/www/src/components/feat/settings/clerk-metadata-popup.tsx
@@ -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}
+
+
+
+ {mdType?.toLocaleUpperCase()} metadata
+
+
+
+ >
+}
\ No newline at end of file
diff --git a/apps/www/src/components/feat/settings/debug-settings.tsx b/apps/www/src/components/feat/settings/debug-settings.tsx
index b4397ac..3eb0c45 100644
--- a/apps/www/src/components/feat/settings/debug-settings.tsx
+++ b/apps/www/src/components/feat/settings/debug-settings.tsx
@@ -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 (
-
- Debug Settings
-
-
-
-
- Generate loading text
-
-
- Generate a random loading text
-
-
-
-
{
- setRandomText(loadingList[Math.floor(Math.random() * loadingList.length)])
- }}>
- Generate
-
-
-
-
-
-
- );
+ return (
+
+ Debug Settings
+
+
+
+ Generate loading text
+
+ Generate a random loading text
+
+
+
+
{
+ setRandomText(
+ loadingList[Math.floor(Math.random() * loadingList.length)],
+ );
+ }}
+ >
+ Generate
+
+
+
+
+
+
+
+
+
+ View Clerk metadata
+
+ View any Clerk metadata for your user.
+
+
+
+
+ Open metadata
+
+
+ window.dispatchEvent(new Event("open-public-clerkmd"))}>Public
+ window.dispatchEvent(new Event("open-unsafe-clerkmd"))}>Unsafe
+
+
+
+
+
+
+ );
}
diff --git a/apps/www/src/components/ui/github.tsx b/apps/www/src/components/ui/github.tsx
index ffe8d3c..ce61f64 100644
--- a/apps/www/src/components/ui/github.tsx
+++ b/apps/www/src/components/ui/github.tsx
@@ -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) => {
diff --git a/apps/www/src/config/sl-mod-db.ts b/apps/www/src/config/sl-mod-db.ts
index cca2228..6415626 100644
--- a/apps/www/src/config/sl-mod-db.ts
+++ b/apps/www/src/config/sl-mod-db.ts
@@ -89,7 +89,7 @@ export const serverModDB: ModDBCategory[] = [
name: "Always Online",
description: "All servers that are always online.",
color: "#a380e0",
- value: new TagFilter(0),
+ value: new TagFilter(2),
icon: ServerCog
}
]
diff --git a/apps/www/src/lib/hooks/use-filters.tsx b/apps/www/src/lib/hooks/use-filters.tsx
index 3b47376..46827c0 100644
--- a/apps/www/src/lib/hooks/use-filters.tsx
+++ b/apps/www/src/lib/hooks/use-filters.tsx
@@ -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);
};
type SortFunction = (object1: K, object2: K) => number;
@@ -57,23 +59,20 @@ export function useFilters(data: OnlineServer[]) {
const [sort, setSort] = useState | 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
+ >) ?? [];
+
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,
};
}
diff --git a/apps/www/src/app/(dashboard)/dashboard/page.tsx b/apps/www/src/lib/hooks/use-modifications-change.tsx
similarity index 79%
rename from apps/www/src/app/(dashboard)/dashboard/page.tsx
rename to apps/www/src/lib/hooks/use-modifications-change.tsx
index c5b5a77..8a3574e 100644
--- a/apps/www/src/app/(dashboard)/dashboard/page.tsx
+++ b/apps/www/src/lib/hooks/use-modifications-change.tsx
@@ -28,6 +28,17 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-export default function Dashboard() {
- return <>Hello world>
+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) {
+
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/apps/www/src/lib/hooks/use-settings-store.tsx b/apps/www/src/lib/hooks/use-settings-store.tsx
index f1b0b36..a886093 100644
--- a/apps/www/src/lib/hooks/use-settings-store.tsx
+++ b/apps/www/src/lib/hooks/use-settings-store.tsx
@@ -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());
+ },
+ };
+}
\ No newline at end of file
diff --git a/apps/www/src/lib/types/filter.ts b/apps/www/src/lib/types/filter.ts
index 769bc6a..16df18c 100644
--- a/apps/www/src/lib/types/filter.ts
+++ b/apps/www/src/lib/types/filter.ts
@@ -32,6 +32,7 @@ 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 {
@@ -49,11 +50,17 @@ export interface Filter {
}
export const supportedFilters: {
- t: (implementation: unknown) => Filter;
ns: string;
+ fi: (identifier: {
+ [key: string]: string | number | boolean;
+ }) => Filter;
}[] = [
{
- t: (i) => new TagFilter(i as string | number),
ns: "app.mhsf.filter.tagFilter",
+ fi: new TagFilter(0, false).fromIdentifier
},
+ {
+ ns: "app.mhsf.filter.categoryFilter",
+ fi: new CategoryFilter(0).fromIdentifier
+ }
];
diff --git a/apps/www/src/pages/api/v1/user/filters/add-filter.ts b/apps/www/src/lib/types/filters/category-filter.ts
similarity index 56%
rename from apps/www/src/pages/api/v1/user/filters/add-filter.ts
rename to apps/www/src/lib/types/filters/category-filter.ts
index 58d80e8..a5b558a 100644
--- a/apps/www/src/pages/api/v1/user/filters/add-filter.ts
+++ b/apps/www/src/lib/types/filters/category-filter.ts
@@ -28,25 +28,37 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-import { NextApiRequest, NextApiResponse } from "next";
-import { getAuth, clerkClient } from "@clerk/nextjs/server";
-import { MongoClient } from "mongodb";
-import { waitUntil } from "@vercel/functions";
-import { supportedFilters } from "@/lib/types/filter";
+import { allCategories } from "@/config/tags";
+import type { MHSFData } from "../data";
+import type { Filter } from "../filter";
+import type { OnlineServer, ServerResponse } from "../mh-server";
-const supportedNamespaces = supportedFilters.map((c) => c.ns);
+export class CategoryFilter implements Filter {
+ categoryIndex: number;
-export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse,
-) {
- const { userId } = getAuth(req);
+ type(): "filter" {
+ return "filter";
+ }
- if (!userId) {
- return res.status(401).json({ error: "Unauthorized" });
+ toIdentifier(): { [key: string]: string | number | boolean } {
+ return { categoryIndex: this.categoryIndex };
}
- const client = new MongoClient(process.env.MONGO_DB as string);
- await client.connect();
+ 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 {
+ if (server.online !== undefined)
+ return allCategories[this.categoryIndex].condition(server.online);
+ return new Promise((r) => r(true));
+ }
+
+ constructor(categoryIndex: number) {
+ this.categoryIndex = categoryIndex;
+ }
}
\ No newline at end of file
diff --git a/apps/www/src/lib/types/filters/tag-filter.ts b/apps/www/src/lib/types/filters/tag-filter.ts
index 46585d0..602366e 100644
--- a/apps/www/src/lib/types/filters/tag-filter.ts
+++ b/apps/www/src/lib/types/filters/tag-filter.ts
@@ -35,13 +35,14 @@ 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 };
+ return { tagId: this.tagId, opposite: this.opposite };
}
getSpecificFilterId(): string {
@@ -51,12 +52,13 @@ export class TagFilter implements Filter {
fromIdentifier(identifier: {
[key: string]: string | number | boolean;
}): Filter {
- return new TagFilter(identifier.tagId as string);
+ return new TagFilter(identifier.tagId as string, identifier.opposite as boolean);
}
- constructor(tagIndex: number | string) {
+ 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: {
@@ -72,8 +74,14 @@ export class TagFilter implements Filter {
).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(result))
+ return new Promise((r) => r(!result))
return result;
}
diff --git a/apps/www/src/middleware.ts b/apps/www/src/middleware.ts
index 14eda54..0bc8822 100644
--- a/apps/www/src/middleware.ts
+++ b/apps/www/src/middleware.ts
@@ -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) => {};
diff --git a/apps/www/src/pages/api/v1/get-status.ts b/apps/www/src/pages/api/v1/get-status.ts
index f7cbf07..7b31c54 100644
--- a/apps/www/src/pages/api/v1/get-status.ts
+++ b/apps/www/src/pages/api/v1/get-status.ts
@@ -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 &&