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 1bc6424..4669e54 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 @@ -150,7 +150,7 @@ export const CodeHighlight = ({ const language = match ? match[1] : undefined; return ( - + {String(children)} ); diff --git a/apps/www/src/components/feat/server-page/server-editor/customizations/server-color-mode-box.tsx b/apps/www/src/components/feat/server-page/server-editor/customizations/server-color-mode-box.tsx index a992562..8e2bd76 100644 --- a/apps/www/src/components/feat/server-page/server-editor/customizations/server-color-mode-box.tsx +++ b/apps/www/src/components/feat/server-page/server-editor/customizations/server-color-mode-box.tsx @@ -1,13 +1,13 @@ import { Input } from "@/components/ui/input"; import { Material } from "@/components/ui/material"; import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectTrigger, - SelectValue, + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { useMHSFServer } from "@/lib/hooks/use-mhsf-server"; @@ -17,78 +17,82 @@ import { Moon, Sun } from "lucide-react"; import { useEffect, useState } from "react"; export function ServerColorModeBox({ - serverData, - minehutData, + serverData, + minehutData, }: { - serverData: ReturnType; - minehutData: ServerResponse; + serverData: ReturnType; + minehutData: ServerResponse; }) { - const [colorModeEnabled, setColorModeEnabled] = useState(false); - const [colorMode, setColorMode] = useState("light"); - - useEffect(() => { - setColorModeEnabled(serverData.server?.customizationData.colorMode !== undefined); - setColorMode(serverData.server?.customizationData.colorMode ?? "light"); - }, [serverData]) + const [colorModeEnabled, setColorModeEnabled] = useState(false); + const [colorMode, setColorMode] = useState("light"); - useEffect(() => { - if (colorMode === "idc") { - setColorModeEnabled(false); - setColorMode("light"); - } - if (colorMode === "dark") - window.dispatchEvent(new Event("force-dark-mode")); + useEffect(() => { + setColorModeEnabled( + serverData.server?.customizationData.colorMode !== null, + ); + setColorMode(serverData.server?.customizationData.colorMode ?? "light"); + }, [serverData]); - if (colorMode === "light") - window.dispatchEvent(new Event("force-light-mode")); - }, [colorMode]); + useEffect(() => { + if (colorMode === "idc") { + setColorModeEnabled(false); + setColorMode("light"); + } + if (colorModeEnabled) { + if (colorMode === "dark") + window.dispatchEvent(new Event("force-dark-mode")); - useEffect(() => { - update(); - }, [colorMode, colorModeEnabled]); + if (colorMode === "light") + window.dispatchEvent(new Event("force-light-mode")); + } else window.dispatchEvent(new Event("force-no-mode")); + }, [colorMode, colorModeEnabled]); - const update = debounce(async () => { - await fetch( - `/api/v1/server/get/${minehutData._id}/settings/change-color-mode${colorModeEnabled !== false ? `?colorMode=${colorMode}` : ""}` - ); - }, 500); + useEffect(() => { + update(); + }, [colorMode, colorModeEnabled]); - return ( - -
- {" "} - Enforce color mode -
+ const update = debounce(async () => { + await fetch( + `/api/v1/server/get/${minehutData._id}/settings/change-color-mode${colorModeEnabled !== false ? `?colorMode=${colorMode}` : ""}`, + ); + }, 500); - -
- ); + return ( + +
+ {" "} + Enforce color mode +
+ + +
+ ); } diff --git a/apps/www/src/components/feat/server-page/server-page.tsx b/apps/www/src/components/feat/server-page/server-page.tsx index 588b57f..7e709bb 100644 --- a/apps/www/src/components/feat/server-page/server-page.tsx +++ b/apps/www/src/components/feat/server-page/server-page.tsx @@ -8,61 +8,71 @@ import { ServerPageButtons } from "./server-page-buttons"; import type { useMHSFServer } from "@/lib/hooks/use-mhsf-server"; import { cn } from "@/lib/utils"; import { useEffect } from "react"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; export function ServerMainPage({ - server, - mhsfData, + server, + mhsfData, }: { - server: ServerResponse; - mhsfData: ReturnType; + server: ServerResponse; + mhsfData: ReturnType; }) { - useEffect(() => { - if (mhsfData.server?.customizationData.colorMode !== undefined) { - if (mhsfData.server?.customizationData.colorMode === "dark") - window.dispatchEvent(new Event("force-dark-mode")); - if (mhsfData.server?.customizationData.colorMode === "light") - window.dispatchEvent(new Event("force-light-mode")); - } - }); + useEffect(() => { + if (mhsfData.server?.customizationData.colorMode !== null) { + if (mhsfData.server?.customizationData.colorMode === "dark") + window.dispatchEvent(new Event("force-dark-mode")); + if (mhsfData.server?.customizationData.colorMode === "light") + window.dispatchEvent(new Event("force-light-mode")); + } + }); - return ( -
- {mhsfData.server?.customizationData.banner && ( - User provided banner for server - )} - -
- -
-

-

-

{server.name}

- - - -
- - - -

-
- - -
- ); + return ( +
+ {mhsfData.server?.customizationData.banner && ( + User provided banner for server + )} + +
+ +
+

+

+

+ + + {server.name[0]} + + {server.name} +

+ + + +
+ + + +

+
+ + +
+ ); } diff --git a/apps/www/src/components/ui/avatar.tsx b/apps/www/src/components/ui/avatar.tsx new file mode 100644 index 0000000..07a20ee --- /dev/null +++ b/apps/www/src/components/ui/avatar.tsx @@ -0,0 +1,79 @@ +/* + * 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 * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/apps/www/src/components/util/theme-provider.tsx b/apps/www/src/components/util/theme-provider.tsx index d57f366..daf20b6 100644 --- a/apps/www/src/components/util/theme-provider.tsx +++ b/apps/www/src/components/util/theme-provider.tsx @@ -49,6 +49,9 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) { window.addEventListener("force-light-mode", () => { setForcedTheme('light'); }); + window.addEventListener("force-no-mode", () => { + setForcedTheme(undefined); + }); }); React.useEffect(() => { diff --git a/apps/www/src/lib/types/data.ts b/apps/www/src/lib/types/data.ts index 6d5a567..fa35a78 100644 --- a/apps/www/src/lib/types/data.ts +++ b/apps/www/src/lib/types/data.ts @@ -36,7 +36,7 @@ export type ActualCustomization = { /** @version 1 @deprecated Use `colorMode` instead */ colorScheme: string | undefined; /** @version 2 */ - colorMode: "dark" | "light" | undefined; + colorMode: "dark" | "light" | null; customizationVersion: number | undefined; } & ( | {