refactor(28-02): simplify VU helpers to use external store
- Remove useState from useVuHelpers (no React state for VU data) - Remove updateVuState, removeVuState, updateVU3 functions - Remove VuMeterComponent (replaced by direct DOM in SessionTrackVU) - Expose vuStore methods via return object - VuContext provides vuStore reference to consumers - Keep legacy renderVU/updateVU for backward compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
96d8f97175
commit
f8214854d9
|
|
@ -1,4 +1,5 @@
|
|||
import React, { createContext, useContext } from 'react';
|
||||
import { vuStore } from '../stores/vuStore';
|
||||
import useVuHelpers from '../hooks/useVuHelpers.js';
|
||||
|
||||
const VuContext = createContext();
|
||||
|
|
@ -6,8 +7,14 @@ const VuContext = createContext();
|
|||
export const VuProvider = ({ children }) => {
|
||||
const vuHelpers = useVuHelpers();
|
||||
|
||||
// Combine vuHelpers with vuStore for context value
|
||||
const value = {
|
||||
...vuHelpers,
|
||||
vuStore,
|
||||
};
|
||||
|
||||
return (
|
||||
<VuContext.Provider value={vuHelpers}>
|
||||
<VuContext.Provider value={value}>
|
||||
{children}
|
||||
</VuContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { vuStore } from '../stores/vuStore';
|
||||
|
||||
const logger = console;
|
||||
|
||||
export default function useVuHelpers() {
|
||||
const [vuStates, setVuStates] = useState({});
|
||||
|
||||
const createQualifiedId = useCallback(mixer => {
|
||||
return (mixer.mode ? 'M' : 'P') + mixer.id;
|
||||
|
|
@ -93,103 +93,15 @@ export default function useVuHelpers() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
// New React-like VU update function
|
||||
const updateVuState = useCallback((mixerId, level, clipping = false) => {
|
||||
setVuStates(prev => ({
|
||||
...prev,
|
||||
[mixerId]: { level, clipping }
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const removeVuState = useCallback((mixerId) => {
|
||||
setVuStates(prev => {
|
||||
const newState = { ...prev };
|
||||
delete newState[mixerId];
|
||||
return newState;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const updateVU3 = useCallback(
|
||||
(mixer, leftValue, leftClipping, rightValue, rightClipping) => {
|
||||
const fqId = createQualifiedId(mixer);
|
||||
//logger.debug('useVuHelpers: updateVU3', { fqId, mixer, leftValue, rightValue });
|
||||
|
||||
// Update React state for declarative rendering
|
||||
updateVuState(fqId, leftValue, leftClipping);
|
||||
},
|
||||
[createQualifiedId, updateVuState]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// Cleanup on unmount
|
||||
setVuStates({});
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Create a proper React component that can be used outside the hook
|
||||
function VuMeterComponent({ mixerId, orientation = 'vertical', lightCount = 16, lightWidth = 15, lightHeight = 10 }) {
|
||||
const vuState = vuStates[mixerId] || { level: 0, clipping: false };
|
||||
const { level, clipping } = vuState;
|
||||
|
||||
const lights = [];
|
||||
for (let i = 0; i < lightCount; i++) {
|
||||
// Calculate if this light should be on based on the level
|
||||
const lightThreshold = (lightCount - i) / lightCount;
|
||||
const isOn = level >= lightThreshold;
|
||||
|
||||
let bgClass = 'vu-bg-secondary'; // Default off state
|
||||
if (isOn) {
|
||||
if (clipping) {
|
||||
bgClass = 'vu-bg-danger'; // Red for clipping
|
||||
} else {
|
||||
const positionFromBottom = lightCount - 1 - i;
|
||||
if (positionFromBottom >= Math.floor(lightCount * 0.75)) { // Red zone (top 25%)
|
||||
bgClass = 'vu-bg-danger';
|
||||
} else if (positionFromBottom >= Math.floor(lightCount * 0.5)) { // Yellow zone (middle 25%)
|
||||
bgClass = 'vu-bg-warning';
|
||||
} else { // Green zone (bottom 50%)
|
||||
bgClass = 'vu-bg-success';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lights.push(
|
||||
<div
|
||||
key={i}
|
||||
className={bgClass}
|
||||
style={{
|
||||
height: `${lightHeight}px`,
|
||||
width: `25px`,
|
||||
marginTop: '1px',
|
||||
borderRadius: '2px',
|
||||
border: '1px solid #eee'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='vu'>
|
||||
<div className="d-flex flex-column" style={{ height: `${lightCount * (lightHeight + 1)}px` }}>
|
||||
{lights}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
// React-like components and functions
|
||||
VuMeter: VuMeterComponent,
|
||||
updateVuState,
|
||||
removeVuState,
|
||||
vuStates,
|
||||
// External store methods (new)
|
||||
updateVuState: vuStore.updateLevel,
|
||||
removeVuState: vuStore.removeLevel,
|
||||
vuStore, // Expose full store for advanced usage
|
||||
|
||||
// Legacy functions for backward compatibility
|
||||
createQualifiedId,
|
||||
renderVU,
|
||||
updateVU,
|
||||
updateVU3
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue