mirror of
https://github.com/DeveloLongScript/MHSF.git
synced 2026-05-07 16:54:59 -05:00
fix: misc
This commit is contained in:
parent
2a58192a14
commit
88e703625c
@ -150,7 +150,7 @@ export const CodeHighlight = ({
|
|||||||
const language = match ? match[1] : undefined;
|
const language = match ? match[1] : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShikiHighlighter language={language} theme="poimandres" {...props}>
|
<ShikiHighlighter language={language?.toLocaleLowerCase()} theme="poimandres" {...props}>
|
||||||
{String(children)}
|
{String(children)}
|
||||||
</ShikiHighlighter>
|
</ShikiHighlighter>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Material } from "@/components/ui/material";
|
import { Material } from "@/components/ui/material";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectGroup,
|
SelectGroup,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectLabel,
|
SelectLabel,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
|
import { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
|
||||||
@ -17,78 +17,82 @@ import { Moon, Sun } from "lucide-react";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export function ServerColorModeBox({
|
export function ServerColorModeBox({
|
||||||
serverData,
|
serverData,
|
||||||
minehutData,
|
minehutData,
|
||||||
}: {
|
}: {
|
||||||
serverData: ReturnType<typeof useMHSFServer>;
|
serverData: ReturnType<typeof useMHSFServer>;
|
||||||
minehutData: ServerResponse;
|
minehutData: ServerResponse;
|
||||||
}) {
|
}) {
|
||||||
const [colorModeEnabled, setColorModeEnabled] = useState(false);
|
const [colorModeEnabled, setColorModeEnabled] = useState(false);
|
||||||
const [colorMode, setColorMode] = useState("light");
|
const [colorMode, setColorMode] = useState("light");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setColorModeEnabled(serverData.server?.customizationData.colorMode !== undefined);
|
setColorModeEnabled(
|
||||||
setColorMode(serverData.server?.customizationData.colorMode ?? "light");
|
serverData.server?.customizationData.colorMode !== null,
|
||||||
}, [serverData])
|
);
|
||||||
|
setColorMode(serverData.server?.customizationData.colorMode ?? "light");
|
||||||
|
}, [serverData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (colorMode === "idc") {
|
if (colorMode === "idc") {
|
||||||
setColorModeEnabled(false);
|
setColorModeEnabled(false);
|
||||||
setColorMode("light");
|
setColorMode("light");
|
||||||
}
|
}
|
||||||
if (colorMode === "dark")
|
if (colorModeEnabled) {
|
||||||
window.dispatchEvent(new Event("force-dark-mode"));
|
if (colorMode === "dark")
|
||||||
|
window.dispatchEvent(new Event("force-dark-mode"));
|
||||||
|
|
||||||
if (colorMode === "light")
|
if (colorMode === "light")
|
||||||
window.dispatchEvent(new Event("force-light-mode"));
|
window.dispatchEvent(new Event("force-light-mode"));
|
||||||
}, [colorMode]);
|
} else window.dispatchEvent(new Event("force-no-mode"));
|
||||||
|
}, [colorMode, colorModeEnabled]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
update();
|
update();
|
||||||
}, [colorMode, colorModeEnabled]);
|
}, [colorMode, colorModeEnabled]);
|
||||||
|
|
||||||
const update = debounce(async () => {
|
const update = debounce(async () => {
|
||||||
await fetch(
|
await fetch(
|
||||||
`/api/v1/server/get/${minehutData._id}/settings/change-color-mode${colorModeEnabled !== false ? `?colorMode=${colorMode}` : ""}`
|
`/api/v1/server/get/${minehutData._id}/settings/change-color-mode${colorModeEnabled !== false ? `?colorMode=${colorMode}` : ""}`,
|
||||||
);
|
);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Material className="flex justify-between items-center p-2 mt-2">
|
<Material className="flex justify-between items-center p-2 mt-2">
|
||||||
<div className="flex items-center font-bold gap-4">
|
<div className="flex items-center font-bold gap-4">
|
||||||
<Switch
|
<Switch
|
||||||
checked={colorModeEnabled}
|
checked={colorModeEnabled}
|
||||||
onCheckedChange={setColorModeEnabled}
|
onCheckedChange={setColorModeEnabled}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
Enforce color mode
|
Enforce color mode
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
disabled={!colorModeEnabled}
|
disabled={!colorModeEnabled}
|
||||||
onValueChange={setColorMode}
|
onValueChange={setColorMode}
|
||||||
value={colorMode}
|
value={colorMode}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px] disabled:hidden">
|
<SelectTrigger className="w-[180px] disabled:hidden">
|
||||||
<SelectValue placeholder="Select mode" />
|
<SelectValue placeholder="Select mode" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectItem value="dark">
|
<SelectItem value="dark">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Moon size={16} />
|
<Moon size={16} />
|
||||||
Dark
|
Dark
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="light">
|
<SelectItem value="light">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Sun size={16} />
|
<Sun size={16} />
|
||||||
Light
|
Light
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="idc">I couldn't care less</SelectItem>
|
<SelectItem value="idc">I couldn't care less</SelectItem>
|
||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</Material>
|
</Material>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,61 +8,71 @@ import { ServerPageButtons } from "./server-page-buttons";
|
|||||||
import type { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
|
import type { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
|
|
||||||
export function ServerMainPage({
|
export function ServerMainPage({
|
||||||
server,
|
server,
|
||||||
mhsfData,
|
mhsfData,
|
||||||
}: {
|
}: {
|
||||||
server: ServerResponse;
|
server: ServerResponse;
|
||||||
mhsfData: ReturnType<typeof useMHSFServer>;
|
mhsfData: ReturnType<typeof useMHSFServer>;
|
||||||
}) {
|
}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mhsfData.server?.customizationData.colorMode !== undefined) {
|
if (mhsfData.server?.customizationData.colorMode !== null) {
|
||||||
if (mhsfData.server?.customizationData.colorMode === "dark")
|
if (mhsfData.server?.customizationData.colorMode === "dark")
|
||||||
window.dispatchEvent(new Event("force-dark-mode"));
|
window.dispatchEvent(new Event("force-dark-mode"));
|
||||||
if (mhsfData.server?.customizationData.colorMode === "light")
|
if (mhsfData.server?.customizationData.colorMode === "light")
|
||||||
window.dispatchEvent(new Event("force-light-mode"));
|
window.dispatchEvent(new Event("force-light-mode"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"xl:px-[100px]",
|
"xl:px-[100px]",
|
||||||
mhsfData.server?.customizationData.banner === undefined
|
mhsfData.server?.customizationData.banner === undefined
|
||||||
? "pt-[150px]"
|
? "pt-[150px]"
|
||||||
: "pt-[300px]"
|
: "pt-[300px]",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{mhsfData.server?.customizationData.banner && (
|
{mhsfData.server?.customizationData.banner && (
|
||||||
<img
|
<img
|
||||||
src={mhsfData.server?.customizationData.banner}
|
src={mhsfData.server?.customizationData.banner}
|
||||||
alt="User provided banner for server"
|
alt="User provided banner for server"
|
||||||
className="rounded align-middle block ml-auto mr-auto absolute left-0 z-0 w-full object-fill"
|
className="rounded align-middle block ml-auto mr-auto absolute left-0 z-0 w-full object-fill"
|
||||||
style={{
|
style={{
|
||||||
maskImage: "linear-gradient(to top, transparent, black)",
|
maskImage: "linear-gradient(to top, transparent, black)",
|
||||||
top: "0",
|
top: "0",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<span className="flex items-center gap-2 w-full relative">
|
<span className="flex items-center gap-2 w-full relative">
|
||||||
<div className="bg-secondary p-4 rounded-lg lg:ml-4">
|
<div className="bg-secondary p-4 rounded-lg lg:ml-4">
|
||||||
<IconDisplay server={server} />
|
<IconDisplay server={server} />
|
||||||
</div>
|
</div>
|
||||||
<p className="w-full">
|
<p className="w-full">
|
||||||
<div className="lg:flex justify-between w-full">
|
<div className="lg:flex justify-between w-full">
|
||||||
<h1 className="text-2xl font-bold">{server.name}</h1>
|
<h1 className="text-2xl font-bold flex items-center gap-1 ml-2">
|
||||||
<span>
|
<Avatar className="h-[32px] w-[32px]">
|
||||||
<ServerPageButtons server={server} mhsfData={mhsfData} />
|
<AvatarImage
|
||||||
</span>
|
src={mhsfData.server?.customizationData.userProfilePicture ?? ""}
|
||||||
</div>
|
alt="Server Owner Image"
|
||||||
<span className="flex items-center gap-2 flex-wrap">
|
/>
|
||||||
<ServerPageTags server={server} className="mt-1" />
|
<AvatarFallback>{server.name[0]}</AvatarFallback>
|
||||||
</span>
|
</Avatar>
|
||||||
</p>
|
{server.name}
|
||||||
</span>
|
</h1>
|
||||||
<Separator className="my-6" />
|
<span>
|
||||||
<ServerRows server={server} mhsfData={mhsfData} />
|
<ServerPageButtons server={server} mhsfData={mhsfData} />
|
||||||
</div>
|
</span>
|
||||||
);
|
</div>
|
||||||
|
<span className="flex items-center gap-2 flex-wrap">
|
||||||
|
<ServerPageTags server={server} className="mt-1" />
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
<Separator className="my-6" />
|
||||||
|
<ServerRows server={server} mhsfData={mhsfData} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
79
apps/www/src/components/ui/avatar.tsx
Normal file
79
apps/www/src/components/ui/avatar.tsx
Normal file
@ -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<typeof AvatarPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AvatarPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
Avatar.displayName = AvatarPrimitive.Root.displayName
|
||||||
|
|
||||||
|
const AvatarImage = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AvatarPrimitive.Image>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AvatarPrimitive.Image
|
||||||
|
ref={ref}
|
||||||
|
className={cn("aspect-square h-full w-full", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
||||||
|
|
||||||
|
const AvatarFallback = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AvatarPrimitive.Fallback
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
||||||
|
|
||||||
|
export { Avatar, AvatarImage, AvatarFallback }
|
||||||
@ -49,6 +49,9 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
|||||||
window.addEventListener("force-light-mode", () => {
|
window.addEventListener("force-light-mode", () => {
|
||||||
setForcedTheme('light');
|
setForcedTheme('light');
|
||||||
});
|
});
|
||||||
|
window.addEventListener("force-no-mode", () => {
|
||||||
|
setForcedTheme(undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ export type ActualCustomization = {
|
|||||||
/** @version 1 @deprecated Use `colorMode` instead */
|
/** @version 1 @deprecated Use `colorMode` instead */
|
||||||
colorScheme: string | undefined;
|
colorScheme: string | undefined;
|
||||||
/** @version 2 */
|
/** @version 2 */
|
||||||
colorMode: "dark" | "light" | undefined;
|
colorMode: "dark" | "light" | null;
|
||||||
customizationVersion: number | undefined;
|
customizationVersion: number | undefined;
|
||||||
} & (
|
} & (
|
||||||
| {
|
| {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user