"use client"; import { useEffect, useMemo, useState } from "react"; import type { ReactNode } from "react"; import { getQueryKey } from "@trpc/react-query"; import { Button, Divider, Group, Pagination, Paper, ScrollArea, Select, SimpleGrid, Stack, Text, } from "@mantine/core"; import { IconClipboardList, IconCpu2, IconReportAnalytics } from "@tabler/icons-react"; import { clientApi } from "@homarr/api/client"; import { useI18n } from "@homarr/translation/client"; import type { TablerIcon } from "@homarr/ui"; import { views } from "."; import { WidgetEmptyState } from "../common/empty-state"; import type { WidgetComponentProps } from "../definition"; import { getUsableWidgetQueryData } from "../common/query-state"; import { useWidgetRuntimeQueries } from "../runtime-hooks"; import { HealthCheckStatus } from "./health-check-status"; import { QueuePanel } from "./panels/queue.panel"; import { StatisticsPanel } from "./panels/statistics.panel"; import { WorkersPanel } from "./panels/workers.panel"; type View = (typeof views)[number]; const viewBySegmentValue = Object.fromEntries(views.map((view) => [view, view])) as Record; const viewIcons = { workers: IconCpu2, queue: IconClipboardList, statistics: IconReportAnalytics, } satisfies Record; type TranscodingControlMode = "buttons" | "select"; const narrowWidthLayout = { minimumWidth: 0, advancedColumns: 1, controlMode: "select" } as const; const widthBreakpoints = [ { minimumWidth: 1100, advancedColumns: 3, controlMode: "buttons" }, { minimumWidth: 700, advancedColumns: 2, controlMode: "buttons" }, { minimumWidth: 560, advancedColumns: 1, controlMode: "buttons" }, narrowWidthLayout, ] as const satisfies readonly { minimumWidth: number; advancedColumns: number; controlMode: TranscodingControlMode; }[]; const getTranscodingWidthLayout = (width: number) => widthBreakpoints.find((candidate) => width >= candidate.minimumWidth) ?? narrowWidthLayout; export default function MediaTranscodingWidget({ integrationIds, options, width, height, displayMode, widgetRuntimeRef, }: WidgetComponentProps<"mediaTranscoding">) { const isAdvanced = displayMode === "advanced"; const queuePageSize = getQueuePageSize(height, isAdvanced); const [queuePagination, setQueuePagination] = useState(() => ({ page: 1, pageSize: queuePageSize, isAdvanced, })); const requestPagination = resolveQueuePagination(queuePagination, queuePageSize, isAdvanced, null); const input = { integrationId: integrationIds[0] ?? "", pageSize: queuePageSize, page: requestPagination.page, }; useWidgetRuntimeQueries(widgetRuntimeRef, [ getQueryKey(clientApi.widget.mediaTranscoding.getDataAsync, input, "query"), ]); const transcodingQuery = clientApi.widget.mediaTranscoding.getDataAsync.useQuery(input); const transcodingData = getUsableWidgetQueryData(transcodingQuery); const [view, setView] = useState(options.defaultView); const t = useI18n("widget.mediaTranscoding"); const totalQueuePages = transcodingData ? Math.max(1, Math.ceil(transcodingData.data.queue.totalCount / queuePageSize)) : null; const resolvedPagination = resolveQueuePagination(queuePagination, queuePageSize, isAdvanced, totalQueuePages); const queuePage = resolvedPagination.page; useEffect(() => { setQueuePagination((current) => { const next = resolveQueuePagination(current, queuePageSize, isAdvanced, totalQueuePages); return current.page === next.page && current.pageSize === next.pageSize && current.isAdvanced === next.isAdvanced ? current : next; }); }, [isAdvanced, queuePageSize, totalQueuePages]); const handleQueuePageChange = (page: number) => { setQueuePagination({ page, pageSize: queuePageSize, isAdvanced }); }; const widthLayout = useMemo(() => getTranscodingWidthLayout(width), [width]); if (!transcodingData) return ; const queuePageCount = totalQueuePages ?? 1; const isTiny = !isAdvanced && (width < 280 || height < 140); const footerLayout = getTranscodingFooterLayout(width, height); if (isAdvanced) { return ( 1 ? "space-between" : "flex-end"} wrap="nowrap"> {queuePageCount > 1 && ( )} ); } return ( {view === "workers" ? ( ) : view === "queue" ? ( ) : ( )} {widthLayout.controlMode === "buttons" ? ( {views.map((value) => { const Icon = viewIcons[value]; return ( ); })} ) : (