import { useEffect, useState } from "react"; import { Button } from "~/shared/components/ui/button"; import { Input } from "~/shared/components/ui/input"; import { api } from "~/shared/lib/api"; interface MqttStatus { status: "connected" | "disconnected" | "error" | "not_configured"; error: string | null; } interface TestResult { connected: boolean; receivedMessage: boolean; error?: string; samplePayload?: string; } interface WebhookPluginInfo { ok: boolean; installed?: boolean; plugin?: { Name?: string; Version?: string } | null; error?: string; } const HANDLEBARS_TEMPLATE = `{ "event": "{{NotificationType}}", "itemId": "{{ItemId}}", "itemType": "{{ItemType}}" }`; function CopyableValue({ label, value, mono = true }: { label: string; value: string; mono?: boolean }) { const [copied, setCopied] = useState(false); const copy = async () => { await navigator.clipboard.writeText(value); setCopied(true); setTimeout(() => setCopied(false), 1500); }; return (
{value}
Close the loop: once Jellyfin finishes its post-ffmpeg rescan, it publishes an event to your MQTT broker. We re-analyze the item, confirming it as done or flipping it back to pending if something didn't stick.
{testResult.samplePayload}
)}
Couldn't reach Jellyfin: {plugin.error}
} {plugin?.ok && !plugin.installed && (⚠ The Webhook plugin is not installed on Jellyfin. Install it from{" "} Jellyfin → Dashboard → Plugins → Catalog → Webhook, restart Jellyfin, then configure an MQTT destination with the values below.
)} {plugin?.ok && plugin.installed && (✓ Plugin detected{plugin.plugin?.Version ? ` (v${plugin.plugin.Version})` : ""}. Add an MQTT destination with:
)}