diff --git a/src/components/session/SessionView.tsx b/src/components/session/SessionView.tsx index 87cb684c..4007da1b 100644 --- a/src/components/session/SessionView.tsx +++ b/src/components/session/SessionView.tsx @@ -9,7 +9,7 @@ import { useSessionDragDrop, type SessionDragState, type SessionDropTarget } fro import { ContextMenuWrapper, ContextMenuSeparator, ContextMenuItem } from '../ui/ContextMenu'; import { ColorSwatchPalette } from '../ui/ColorSwatchPalette'; import { SessionMixer } from './SessionMixer'; -import type { Clip, Track, SessionLaunchQuantization, SessionLaunchMode, SessionClipSlot, SessionPendingLaunch, SessionScene, SceneFollowActionType } from '../../types/project'; +import type { Clip, Track, SessionLaunchQuantization, SessionLaunchMode, SessionClipSlot, SessionPendingLaunch, SessionScene, SceneFollowActionType, FollowActionType, FollowActionConfig } from '../../types/project'; const LAUNCH_MODE_OPTIONS: SessionLaunchMode[] = ['trigger', 'gate', 'toggle', 'repeat']; @@ -80,8 +80,20 @@ interface SlotContextMenuState { currentColor: string | null; legato: boolean; currentLaunchMode: SessionLaunchMode; + followAction?: FollowActionConfig; } +const CLIP_FOLLOW_ACTION_OPTIONS: { value: FollowActionType; label: string }[] = [ + { value: 'stop', label: 'Stop' }, + { value: 'again', label: 'Again' }, + { value: 'previous', label: 'Previous' }, + { value: 'next', label: 'Next' }, + { value: 'first', label: 'First' }, + { value: 'last', label: 'Last' }, + { value: 'any', label: 'Any' }, + { value: 'other', label: 'Other' }, +]; + export function SessionView() { const project = useProjectStore((s) => s.project); @@ -94,6 +106,8 @@ export function SessionView() { const setSessionSlotColor = useProjectStore((s) => s.setSessionSlotColor); const setSessionSlotLegato = useProjectStore((s) => s.setSessionSlotLegato); const setSessionSlotLaunchMode = useProjectStore((s) => s.setSessionSlotLaunchMode); + const setSessionSlotFollowAction = useProjectStore((s) => s.setSessionSlotFollowAction); + const setSessionFollowActionsEnabled = useProjectStore((s) => s.setSessionFollowActionsEnabled); const selectedSessionSlot = useUIStore((s) => s.selectedSessionSlot); const setSelectedSessionSlot = useUIStore((s) => s.setSelectedSessionSlot); const setKeyboardContext = useUIStore((s) => s.setKeyboardContext); @@ -135,6 +149,20 @@ export function SessionView() { } }, [colorMenu, setSessionSlotLaunchMode]); + const handleFollowActionChange = useCallback((field: string, value: string | number | boolean) => { + if (!colorMenu) return; + setSessionSlotFollowAction(colorMenu.slotId, { [field]: value }); + // Update local state to reflect change immediately + setColorMenu((prev) => { + if (!prev) return null; + const defaultFA: FollowActionConfig = { actionA: 'next', actionB: 'stop', chanceA: 1, time: 4, enabled: true }; + return { + ...prev, + followAction: { ...(prev.followAction ?? defaultFA), [field]: value }, + }; + }); + }, [colorMenu, setSessionSlotFollowAction]); + // Set keyboard context to 'session' on mount, restore previous on unmount useEffect(() => { const previousScope = useUIStore.getState().keyboardContext.scope; @@ -166,6 +194,7 @@ export function SessionView() { const sessionSlots = project.session?.slots ?? []; const pendingLaunches = project.session?.pendingLaunches ?? []; const scenes = project.session?.scenes ?? []; + const followActionsEnabled = project.session?.followActionsEnabled !== false; return (
@@ -190,6 +219,17 @@ export function SessionView() { ))} +