diff --git a/apps/desktop/src/components/mqtt/MqttAdminConsole.vue b/apps/desktop/src/components/mqtt/MqttAdminConsole.vue index 9fd584ec6a..fff1ecefa5 100644 --- a/apps/desktop/src/components/mqtt/MqttAdminConsole.vue +++ b/apps/desktop/src/components/mqtt/MqttAdminConsole.vue @@ -9,7 +9,7 @@ import TopicTreeNode from "./TopicTreeNode.vue"; import MqttPublishPanel from "./MqttPublishDialog.vue"; import { decodePayload, PAYLOAD_ENCODINGS, PAYLOAD_ENCODING_LABELS, type PayloadEncoding } from "@/lib/mqtt/mqttPayloadCodec"; import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStorage"; -import { ChevronDown, ChevronUp } from "@lucide/vue"; +import { ChevronDown, ChevronUp, Pause, Play } from "@lucide/vue"; interface Props { connectionId: string; @@ -27,6 +27,7 @@ const selectedTopic = ref(props.initialTopic ?? ""); const loading = ref(true); const error = ref(null); const pollingTimer = ref | null>(null); +const messagesPaused = ref(false); const displayEncoding = ref("plaintext"); const topicSearch = ref(""); const showSubscriptionDialog = ref(false); @@ -218,8 +219,10 @@ async function handleClearMessages() { function startPolling() { stopPolling(); pollingTimer.value = setInterval(async () => { + if (messagesPaused.value) return; try { - messages.value = (await mqttGetMessages(props.connectionId, selectedTopic.value || undefined, 50)) as MqttMessage[]; + const nextMessages = (await mqttGetMessages(props.connectionId, selectedTopic.value || undefined, 50)) as MqttMessage[]; + if (!messagesPaused.value) messages.value = nextMessages; } catch { /* ignore polling errors */ } @@ -233,6 +236,10 @@ function stopPolling() { } } +function toggleMessagesPaused() { + messagesPaused.value = !messagesPaused.value; +} + function formatMessagePayload(msg: MqttMessage): string { if (displayEncoding.value === "plaintext" && msg.payloadText != null) return msg.payloadText; return decodePayload(msg.payloadBase64, displayEncoding.value); @@ -326,6 +333,11 @@ onUnmounted(stopPolling); +