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:
@@ -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 && (
|
||||
|
||||
Reference in New Issue
Block a user