fix: toolbar buttons clickable, add node delete
Fixes:
- SVG mousedown handler now ignores clicks outside SVG (toolbar works)
- Right-click node -> Destroy Node to delete virtual devices
- POST /api/destroy-node {node_id} endpoint (uses pw-cli destroy)
Node context menu shows node name and destroy button.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
let hoveredPort = $state<number | null>(null);
|
||||
let selectedEdge = $state<string | null>(null);
|
||||
let contextMenu = $state<{ x: number; y: number; linkId: number; outputPortId: number; inputPortId: number; pinned: boolean } | null>(null);
|
||||
let nodeContextMenu = $state<{ x: number; y: number; nodeId: number; nodeName: string } | null>(null);
|
||||
|
||||
// Filters
|
||||
let showAudio = $state(true);
|
||||
@@ -234,6 +235,9 @@
|
||||
|
||||
// Mouse handlers
|
||||
function onMouseDown(e: MouseEvent) {
|
||||
// Ignore clicks outside the SVG (toolbar, dialogs, etc.)
|
||||
if (svgEl && !svgEl.contains(e.target as Node)) return;
|
||||
|
||||
contextMenu = null;
|
||||
if (e.button === 2) return;
|
||||
const pt = svgPoint(e);
|
||||
@@ -352,6 +356,8 @@
|
||||
function onContextMenu(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
// Right-click on edge
|
||||
if (target.classList.contains('edge-path')) {
|
||||
const edgeId = target.dataset.edgeId;
|
||||
const link = $links.find(l => String(l.id) === edgeId);
|
||||
@@ -365,7 +371,40 @@
|
||||
pinned: $patchbay.pinned_connections.includes(link.id),
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Right-click on node
|
||||
const nodeGroup = target.closest('.node-group') as HTMLElement;
|
||||
if (nodeGroup) {
|
||||
const nodeId = Number(nodeGroup.dataset.nodeId);
|
||||
const nd = $nodes.find(n => n.id === nodeId);
|
||||
if (nd) {
|
||||
nodeContextMenu = { x: e.clientX, y: e.clientY, nodeId, nodeName: nd.name };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function unloadNodeModule() {
|
||||
if (!nodeContextMenu) return;
|
||||
// Try to find and unload the module that created this node
|
||||
// Use pactl to unload by looking up the module
|
||||
fetch('/api/load-module', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ module: 'module-null-sink', args: '' }),
|
||||
}).catch(() => {});
|
||||
|
||||
// Actually, just use the destroy approach via pactl
|
||||
// We need to find the module ID. Let's use a different endpoint.
|
||||
// For now, use pw-cli to destroy the node
|
||||
const name = nodeContextMenu.nodeName;
|
||||
fetch('/api/destroy-node', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ node_id: nodeContextMenu.nodeId }),
|
||||
}).catch(() => {});
|
||||
nodeContextMenu = null;
|
||||
}
|
||||
|
||||
function onKey(e: KeyboardEvent) {
|
||||
@@ -379,7 +418,7 @@
|
||||
onDestroy(() => { destroyGraph(); });
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={onKey} onclick={() => { contextMenu = null; showVirtualMenu = false; }} />
|
||||
<svelte:window onkeydown={onKey} onclick={() => { contextMenu = null; nodeContextMenu = null; showVirtualMenu = false; }} />
|
||||
|
||||
<div class="wrap">
|
||||
<div class="toolbar">
|
||||
@@ -584,6 +623,20 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if nodeContextMenu}
|
||||
<div class="ctx" style="left:{nodeContextMenu.x}px;top:{nodeContextMenu.y}px" role="menu">
|
||||
<div class="ctx-title">{nodeContextMenu.nodeName}</div>
|
||||
<button onclick={() => {
|
||||
fetch('/api/destroy-node', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ node_id: nodeContextMenu!.nodeId }),
|
||||
}).catch(() => {});
|
||||
nodeContextMenu = null;
|
||||
}}>Destroy Node</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Hide Nodes Dialog -->
|
||||
{#if showHideDialog}
|
||||
<div class="dialog">
|
||||
@@ -749,6 +802,11 @@
|
||||
font-size: 12px; cursor: pointer; text-align: left; font-family: monospace;
|
||||
}
|
||||
.ctx button:hover { background: #444; }
|
||||
.ctx-title {
|
||||
padding: 4px 16px; font-size: 9px; color: #666;
|
||||
border-bottom: 1px solid #444; font-family: monospace;
|
||||
max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Dialogs */
|
||||
.dialog {
|
||||
|
||||
Reference in New Issue
Block a user