Compare commits

..

No commits in common. "926d45b4be831c3cac3912bf1a88dc0d09d01f11" and "34becfe9793708499e0200fae7f00f30c780eb0b" have entirely different histories.

7 changed files with 27 additions and 68 deletions

View File

@ -82,20 +82,12 @@ export default function ServerListClient() {
? sortedServers ? sortedServers
: sortedServers.filter((server) => server.tag === tag); : sortedServers.filter((server) => server.tag === tag);
const tagCountMap: Record<string, number> = {};
sortedServers.forEach((server) => {
if (server.tag) {
tagCountMap[server.tag] = (tagCountMap[server.tag] || 0) + 1;
}
});
return ( return (
<> <>
{getEnv("NEXT_PUBLIC_ShowTag") === "true" && uniqueTags.length > 1 && ( {getEnv("NEXT_PUBLIC_ShowTag") === "true" && uniqueTags.length > 1 && (
<Switch <Switch
allTag={uniqueTags} allTag={uniqueTags}
nowTag={tag} nowTag={tag}
tagCountMap={tagCountMap}
onTagChange={handleTagChange} onTagChange={handleTagChange}
/> />
)} )}

BIN
bun.lockb

Binary file not shown.

View File

@ -9,17 +9,16 @@ import {
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { localeItems } from "@/i18n-metadata"; import { localeItems } from "@/i18n-metadata";
import { setUserLocale } from "@/i18n/locale"; import { setUserLocale } from "@/i18n/locale";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import { useLocale } from "next-intl"; import { useLocale } from "next-intl";
import * as React from "react"; import * as React from "react";
export function LanguageSwitcher() { export function LanguageSwitcher() {
const locale = useLocale(); const locale = useLocale();
const handleSelect = (e: Event, newLocale: string) => { function onChange(value: string) {
e.preventDefault(); // 阻止默认的关闭行为 const locale = value;
setUserLocale(newLocale); setUserLocale(locale);
}; }
return ( return (
<DropdownMenu> <DropdownMenu>
@ -33,15 +32,10 @@ export function LanguageSwitcher() {
<span className="sr-only">Change language</span> <span className="sr-only">Change language</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="flex flex-col gap-0.5" align="end"> <DropdownMenuContent align="end">
{localeItems.map((item) => ( {localeItems.map((item) => (
<DropdownMenuItem <DropdownMenuItem key={item.code} onClick={() => onChange(item.code)}>
key={item.code} {item.name}
onSelect={(e) => handleSelect(e, item.code)}
className={locale === item.code ? "bg-muted gap-3" : ""}
>
{item.name}{" "}
{locale === item.code && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
))} ))}
</DropdownMenuContent> </DropdownMenuContent>

View File

@ -8,12 +8,10 @@ import React, { createRef, useEffect, useRef } from "react";
export default function Switch({ export default function Switch({
allTag, allTag,
nowTag, nowTag,
tagCountMap,
onTagChange, onTagChange,
}: { }: {
allTag: string[]; allTag: string[];
nowTag: string; nowTag: string;
tagCountMap: Record<string, number>;
onTagChange: (tag: string) => void; onTagChange: (tag: string) => void;
}) { }) {
const scrollRef = useRef<HTMLDivElement>(null); const scrollRef = useRef<HTMLDivElement>(null);
@ -86,14 +84,9 @@ export default function Switch({
/> />
)} )}
<div className="relative z-20 flex items-center gap-1"> <div className="relative z-20 flex items-center gap-1">
<div className="whitespace-nowrap flex items-center gap-2"> <p className="whitespace-nowrap">
{tag === "defaultTag" ? t("defaultTag") : tag}{" "} {tag === "defaultTag" ? t("defaultTag") : tag}
{tag !== "defaultTag" && ( </p>
<div className="w-fit px-1.5 rounded-full bg-muted">
{tagCountMap[tag]}
</div>
)}
</div>
</div> </div>
</div> </div>
))} ))}

View File

@ -7,21 +7,14 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import { Moon, Sun } from "lucide-react"; import { Moon, Sun } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import * as React from "react";
export function ModeToggle() { export function ModeToggle() {
const { setTheme, theme } = useTheme(); const { setTheme } = useTheme();
const t = useTranslations("ThemeSwitcher"); const t = useTranslations("ThemeSwitcher");
const handleSelect = (e: Event, newTheme: string) => {
e.preventDefault();
setTheme(newTheme);
};
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
@ -35,27 +28,15 @@ export function ModeToggle() {
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="flex flex-col gap-0.5" align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem <DropdownMenuItem onClick={() => setTheme("light")}>
className={cn({ "gap-3 bg-muted": theme === "light" })} {t("Light")}
onSelect={(e) => handleSelect(e, "light")}
>
{t("Light")}{" "}
{theme === "light" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem onClick={() => setTheme("dark")}>
className={cn({ "gap-3 bg-muted": theme === "dark" })} {t("Dark")}
onSelect={(e) => handleSelect(e, "dark")}
>
{t("Dark")}{" "}
{theme === "dark" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem onClick={() => setTheme("system")}>
className={cn({ "gap-3 bg-muted": theme === "system" })} {t("System")}
onSelect={(e) => handleSelect(e, "system")}
>
{t("System")}{" "}
{theme === "system" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>

View File

@ -64,7 +64,7 @@ const DropdownMenuContent = React.forwardRef<
ref={ref} ref={ref}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"z-50 overflow-hidden rounded-md border bg-popover p-1.5 text-popover-foreground shadow-2xl dark:shadow-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "z-50 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg shadow-neutral-200/50 dark:shadow-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className, className,
)} )}
{...props} {...props}
@ -82,7 +82,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex cursor-default select-none items-center rounded-[10px] px-2 py-1.5 text-xs font-medium outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-xs font-medium outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8", inset && "pl-8",
className, className,
)} )}

View File

@ -1,6 +1,6 @@
{ {
"name": "nezha-dash", "name": "nezha-dash",
"version": "1.2.9", "version": "1.2.8",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 3020", "dev": "next dev -p 3020",
@ -12,7 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@ducanh2912/next-pwa": "^10.2.9", "@ducanh2912/next-pwa": "^10.2.9",
"@heroicons/react": "^2.1.5",
"@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-navigation-menu": "^1.2.1", "@radix-ui/react-navigation-menu": "^1.2.1",
@ -20,10 +19,10 @@
"@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.4", "@radix-ui/react-tooltip": "^1.1.3",
"@trivago/prettier-plugin-sort-imports": "^4.3.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/luxon": "^3.4.2", "@types/luxon": "^3.4.2",
"@typescript-eslint/eslint-plugin": "^8.14.0", "@typescript-eslint/eslint-plugin": "^8.13.0",
"caniuse-lite": "^1.0.30001680", "caniuse-lite": "^1.0.30001680",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -35,7 +34,7 @@
"luxon": "^3.5.0", "luxon": "^3.5.0",
"next": "^15.0.3", "next": "^15.0.3",
"next-auth": "^5.0.0-beta.25", "next-auth": "^5.0.0-beta.25",
"next-intl": "^3.25.1", "next-intl": "^3.25.0",
"next-runtime-env": "^3.2.2", "next-runtime-env": "^3.2.2",
"next-themes": "^0.4.3", "next-themes": "^0.4.3",
"react": "19.0.0-rc-02c0e824-20241028", "react": "19.0.0-rc-02c0e824-20241028",
@ -48,7 +47,7 @@
"swr": "^2.2.6-beta.4", "swr": "^2.2.6-beta.4",
"tailwind-merge": "^2.5.4", "tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"typescript-eslint": "^8.14.0" "typescript-eslint": "^8.13.0"
}, },
"devDependencies": { "devDependencies": {
"eslint-plugin-turbo": "^2.2.3", "eslint-plugin-turbo": "^2.2.3",
@ -60,7 +59,7 @@
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^9.14.0", "eslint": "^9.14.0",
"eslint-config-next": "^15.0.3", "eslint-config-next": "^15.0.3",
"postcss": "^8.4.49", "postcss": "^8.4.48",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.8", "prettier-plugin-tailwindcss": "^0.6.8",
"tailwindcss": "^3.4.14", "tailwindcss": "^3.4.14",