Merge feature/node-aliases into master

This commit is contained in:
joren
2026-03-30 20:08:21 +02:00
3 changed files with 58 additions and 4 deletions

View File

@@ -12,6 +12,7 @@
setAutoPin, setAutoDisconnect,
saveProfile, loadProfile, deleteProfile,
setNodeVolume, setNodeMute,
setAlias,
createNullSink, createLoopback, loadModule,
getQuantum, setQuantum,
} from '../lib/stores';
@@ -29,6 +30,8 @@
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);
let showPropsDialog = $state<number | null>(null); // node ID or null
let renameDialog = $state<{ pwName: string } | null>(null);
let renameInput = $state('');
// Filters
let showAudio = $state(true);
@@ -128,6 +131,11 @@
return nodeName;
}
// Return custom alias, otherwise nick, otherwise PW name
function displayName(nd: { name: string; nick: string }): string {
return $patchbay.aliases?.[nd.name] || nd.nick || nd.name;
}
// Build computed layout
let graphNodes = $derived.by(() => {
const n = $nodes;
@@ -593,7 +601,7 @@
<rect x={nd.x} y={nd.y} width={nd.width} height="22" rx="4" fill={headerBg} />
<rect x={nd.x} y={nd.y + 16} width={nd.width} height="6" fill={headerBg} />
<text x={nd.x + 6} y={nd.y + 15} font-size="10" font-family="monospace" fill="#ddd" font-weight="bold">
{nd.nick || nd.name}
{displayName(nd)}
</text>
<text x={nd.x + nd.width - 6} y={nd.y + 15} font-size="9" font-family="monospace" fill="#777" text-anchor="end">
[{nd.node_type}]
@@ -680,8 +688,13 @@
{#if nodeContextMenu}
<div class="ctx" style="left:{nodeContextMenu.x}px;top:{nodeContextMenu.y}px" role="menu">
<div class="ctx-title">{nodeContextMenu.nodeName}</div>
<div class="ctx-title">{$patchbay.aliases?.[nodeContextMenu.nodeName] || nodeContextMenu.nodeName}</div>
<button onclick={() => { showPropsDialog = nodeContextMenu!.nodeId; nodeContextMenu = null; }}>Properties</button>
<button onclick={() => {
renameDialog = { pwName: nodeContextMenu!.nodeName };
renameInput = $patchbay.aliases?.[nodeContextMenu!.nodeName] ?? '';
nodeContextMenu = null;
}}>Rename</button>
<button onclick={() => {
fetch('/api/destroy-node', {
method: 'POST',
@@ -699,7 +712,7 @@
{#if nd}
<div class="dialog">
<div class="dialog-header">
<span>Properties: {nd.nick || nd.name}</span>
<span>Properties: {displayName(nd)}</span>
<button class="close" onclick={() => { showPropsDialog = null; }}>X</button>
</div>
<div class="dialog-body">
@@ -730,6 +743,31 @@
{/if}
{/if}
<!-- Rename Node Dialog -->
{#if renameDialog}
<div class="dialog" style="right:auto;left:50%;top:50%;transform:translate(-50%,-50%);width:280px">
<div class="dialog-header">
<span>Rename Node</span>
<button class="close" onclick={() => { renameDialog = null; }}>X</button>
</div>
<div class="dialog-body">
<p class="hint" style="word-break:break-all">{renameDialog.pwName}</p>
<div class="input-row">
<input
class="dlg-input"
bind:value={renameInput}
placeholder="Custom display name (leave blank to reset)"
onkeydown={(e) => { if (e.key === 'Enter') { setAlias(renameDialog!.pwName, renameInput); renameDialog = null; } }}
/>
</div>
<div class="input-row" style="justify-content:flex-end;gap:6px">
<button onclick={() => { setAlias(renameDialog!.pwName, ''); renameDialog = null; }}>Reset</button>
<button onclick={() => { setAlias(renameDialog!.pwName, renameInput); renameDialog = null; }}>Save</button>
</div>
</div>
</div>
{/if}
<!-- Hide Nodes Dialog -->
{#if showHideDialog}
<div class="dialog">

View File

@@ -19,6 +19,7 @@ export const patchbay = writable<PatchbayState>({
pinned_connections: [],
hide_rules: [],
merge_rules: [],
aliases: {},
});
// Port/node lookups
@@ -82,7 +83,7 @@ export async function initGraph() {
if (res.ok) {
const data = await res.json();
if (data && data.profiles) {
patchbay.set(data as PatchbayState);
patchbay.set({ ...data, aliases: data.aliases ?? {} } as PatchbayState);
}
}
} catch {}
@@ -357,6 +358,20 @@ export function deleteProfile(name: string) {
savePatchbayState();
}
// Node aliases (custom display names, keyed by PW node name)
export function setAlias(pwName: string, alias: string) {
patchbay.update(pb => {
const aliases = { ...pb.aliases };
if (alias.trim()) {
aliases[pwName] = alias.trim();
} else {
delete aliases[pwName]; // empty string = remove alias
}
return { ...pb, aliases };
});
savePatchbayState();
}
// Volume control
export async function setNodeVolume(nodeId: number, volume: number) {
try {

View File

@@ -85,4 +85,5 @@ export interface PatchbayState {
pinned_connections: number[];
hide_rules: string[];
merge_rules: string[];
aliases: Record<string, string>; // PW node name → custom display name
}