feat: restore automation controls with AutomationHeader component

- Import and use AutomationHeader component in automation bar
- Add parameter selection dropdown (Volume, Pan, Effect parameters)
- Add automation mode controls (Read, Write, Touch, Latch)
- Add lane height controls (increase/decrease buttons)
- Add show/hide toggle button
- Build available parameters dynamically from track effects
- All controls properly wired to update track automation state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-19 13:13:12 +01:00
parent 0babc469cc
commit 14a9c6e163

View File

@@ -10,6 +10,7 @@ import type { Track as TrackType } from '@/types/track';
import { DEFAULT_TRACK_HEIGHT, COLLAPSED_TRACK_HEIGHT, MIN_TRACK_HEIGHT } from '@/types/track';
import { createEffect, type EffectType, EFFECT_NAMES } from '@/lib/audio/effects/chain';
import { AutomationLane } from '@/components/automation/AutomationLane';
import { AutomationHeader } from '@/components/automation/AutomationHeader';
import type { AutomationPoint as AutomationPointType } from '@/types/automation';
import { createAutomationPoint } from '@/lib/audio/automation/utils';
import { EffectDevice } from '@/components/effects/EffectDevice';
@@ -303,16 +304,44 @@ export function TrackList({
</div>
{/* Automation Bar - Collapsible - Fixed height when expanded */}
{!track.collapsed && (
{!track.collapsed && (() => {
const selectedParam = track.automation.selectedParameterId || 'volume';
const currentLane = track.automation.lanes.find(
l => l.parameterId === selectedParam
);
// Build available parameters list
const availableParameters: Array<{ id: string; name: string }> = [
{ id: 'volume', name: 'Volume' },
{ id: 'pan', name: 'Pan' },
];
// Add effect parameters
track.effectChain.effects.forEach((effect) => {
if (effect.parameters) {
Object.keys(effect.parameters).forEach((paramKey) => {
const parameterId = `effect.${effect.id}.${paramKey}`;
const paramName = `${effect.name} - ${paramKey.charAt(0).toUpperCase() + paramKey.slice(1)}`;
availableParameters.push({ id: parameterId, name: paramName });
});
}
});
return (
<div className="flex-shrink-0 bg-card/90 backdrop-blur-sm">
{/* Automation Header - Clickable to toggle */}
<div
className="flex items-center gap-2 px-3 py-1.5 cursor-pointer hover:bg-accent/30 transition-colors"
onClick={() => {
const selectedParam = track.automation.selectedParameterId || 'volume';
const currentLane = track.automation.lanes.find(
l => l.parameterId === selectedParam
);
<AutomationHeader
parameterName={currentLane?.parameterName || 'Volume'}
visible={currentLane?.visible ?? true}
mode={currentLane?.mode || 'read'}
color={currentLane?.color}
availableParameters={availableParameters}
selectedParameterId={selectedParam}
onParameterChange={(parameterId) => {
onUpdateTrack(track.id, {
automation: { ...track.automation, selectedParameterId: parameterId },
});
}}
onToggleVisible={() => {
if (currentLane) {
const updatedLanes = track.automation.lanes.map((l) =>
l.id === currentLane.id ? { ...l, visible: !l.visible } : l
@@ -322,17 +351,28 @@ export function TrackList({
});
}
}}
>
{track.automation.lanes.find(l => l.parameterId === (track.automation.selectedParameterId || 'volume'))?.visible ? (
<ChevronDown className="h-3 w-3 text-muted-foreground" />
) : (
<ChevronRight className="h-3 w-3 text-muted-foreground" />
)}
<span className="text-xs font-medium">Automation</span>
<span className="text-xs text-muted-foreground">
{track.automation.selectedParameterId || 'Volume'}
</span>
</div>
onModeChange={(mode) => {
if (currentLane) {
const updatedLanes = track.automation.lanes.map((l) =>
l.id === currentLane.id ? { ...l, mode } : l
);
onUpdateTrack(track.id, {
automation: { ...track.automation, lanes: updatedLanes },
});
}
}}
onHeightChange={(delta) => {
if (currentLane) {
const newHeight = Math.max(60, Math.min(200, currentLane.height + delta));
const updatedLanes = track.automation.lanes.map((l) =>
l.id === currentLane.id ? { ...l, height: newHeight } : l
);
onUpdateTrack(track.id, {
automation: { ...track.automation, lanes: updatedLanes },
});
}
}}
/>
{/* Automation Lane Content - Collapsible */}
{track.automation.lanes
@@ -391,7 +431,8 @@ export function TrackList({
/>
))}
</div>
)}
);
})()}
{/* Effects Bar - Collapsible - Fixed height when expanded */}
{!track.collapsed && (