feat(widget): add minecraft server status widget (#1801)

This commit is contained in:
Meier Lukas
2024-12-31 09:45:48 +01:00
committed by GitHub
parent b8a155dd08
commit 0ebf4bc55e
13 changed files with 248 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ import * as mediaRequestsList from "./media-requests/list";
import * as mediaRequestsStats from "./media-requests/stats";
import * as mediaServer from "./media-server";
import * as mediaTranscoding from "./media-transcoding";
import * as minecraftServerStatus from "./minecraft/server-status";
import * as notebook from "./notebook";
import type { WidgetOptionDefinition } from "./options";
import * as rssFeed from "./rssFeed";
@@ -54,6 +55,7 @@ export const widgetImports = {
indexerManager,
healthMonitoring,
mediaTranscoding,
minecraftServerStatus,
} satisfies WidgetImportRecord;
export type WidgetImports = typeof widgetImports;

View File

@@ -0,0 +1,61 @@
"use client";
import { Box, Flex, Group, Text, Tooltip } from "@mantine/core";
import { IconUsersGroup } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { useScopedI18n } from "@homarr/translation/client";
import type { WidgetComponentProps } from "../../definition";
export default function MinecraftServerStatusWidget({ options }: WidgetComponentProps<"minecraftServerStatus">) {
const [{ data }] = clientApi.widget.minecraft.getServerStatus.useSuspenseQuery(options);
const utils = clientApi.useUtils();
clientApi.widget.minecraft.subscribeServerStatus.useSubscription(options, {
onData(data) {
utils.widget.minecraft.getServerStatus.setData(options, {
data,
timestamp: new Date(),
});
},
});
const tStatus = useScopedI18n("widget.minecraftServerStatus.status");
const title = options.title.trim().length > 0 ? options.title : options.domain;
return (
<Flex
className="minecraftServerStatus-wrapper"
h="100%"
w="100%"
direction="column"
p="7.5cqmin"
justify="center"
align="center"
>
<Group gap="5cqmin" wrap="nowrap" align="center">
<Tooltip label={data.online ? tStatus("online") : tStatus("offline")}>
<Box w="8cqmin" h="8cqmin" bg={data.online ? "teal" : "red"} style={{ borderRadius: "100%" }}></Box>
</Tooltip>
<Text size="10cqmin" fw="bold">
{title}
</Text>
</Group>
{data.online && (
<>
<img
style={{ flex: 1, transform: "scale(0.8)", objectFit: "contain" }}
alt={`minecraft icon ${options.domain}`}
src={data.icon}
/>
<Group gap="2cqmin" c="gray.6" align="center">
<IconUsersGroup style={{ width: "10cqmin", height: "10cqmin" }} />
<Text size="10cqmin">
{data.players.online}/{data.players.max}
</Text>
</Group>
</>
)}
</Flex>
);
}

View File

@@ -0,0 +1,15 @@
import { IconBrandMinecraft } from "@tabler/icons-react";
import { z } from "@homarr/validation";
import { createWidgetDefinition } from "../../definition";
import { optionsBuilder } from "../../options";
export const { componentLoader, definition } = createWidgetDefinition("minecraftServerStatus", {
icon: IconBrandMinecraft,
options: optionsBuilder.from((factory) => ({
title: factory.text({ defaultValue: "" }),
domain: factory.text({ defaultValue: "hypixel.net", validate: z.string().nonempty() }),
isBedrockServer: factory.switch({ defaultValue: false }),
})),
}).withDynamicImport(() => import("./component"));