feat: ajout dropdowns gain par route dans matrice routing
- Dropdown gain -12dB à +6dB pour chaque route active - Interface visuelle améliorée (checkbox + gain) - Gestion gains input->group et group->output - Sauvegarde gains dans config.yaml - Design responsive mobile
This commit is contained in:
@@ -81,7 +81,7 @@ define(['./workbox-290dd570'], (function (workbox) { 'use strict';
|
||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.pjhah2a023"
|
||||
"revision": "0.guj84039cv8"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -84,15 +84,25 @@
|
||||
|
||||
.matrix-cell {
|
||||
background: var(--color-bg);
|
||||
padding: var(--spacing-md);
|
||||
min-height: 40px;
|
||||
min-width: 60px;
|
||||
cursor: pointer;
|
||||
padding: var(--spacing-sm);
|
||||
min-height: 60px;
|
||||
min-width: 80px;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-xs);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cell-checkbox {
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.matrix-cell:hover {
|
||||
@@ -114,6 +124,25 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gain-select {
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
font-size: 0.75rem;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: var(--color-text);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gain-select:focus {
|
||||
outline: none;
|
||||
border-color: rgba(255, 255, 255, 0.6);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.matrix-header-cell,
|
||||
.matrix-label-cell {
|
||||
@@ -123,10 +152,15 @@
|
||||
}
|
||||
|
||||
.matrix-cell {
|
||||
min-width: 50px;
|
||||
min-height: 35px;
|
||||
min-width: 70px;
|
||||
min-height: 50px;
|
||||
padding: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.gain-select {
|
||||
font-size: 0.7rem;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -147,11 +181,16 @@
|
||||
}
|
||||
|
||||
.matrix-cell {
|
||||
min-width: 40px;
|
||||
min-height: 30px;
|
||||
min-width: 65px;
|
||||
min-height: 45px;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.gain-select {
|
||||
font-size: 0.65rem;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,39 @@ function AudioRoutingMatrix({ groups, channelNames }) {
|
||||
return routing.groupToOutput[groupId]?.includes(outputId) || false;
|
||||
};
|
||||
|
||||
const getGainForInputToGroup = (inputId, groupId) => {
|
||||
const key = `in_${inputId}_${groupId}`;
|
||||
return routing.gains?.[key] || 0.0;
|
||||
};
|
||||
|
||||
const getGainForGroupToOutput = (groupId, outputId) => {
|
||||
const key = `${groupId}_out_${outputId}`;
|
||||
return routing.gains?.[key] || 0.0;
|
||||
};
|
||||
|
||||
const setGainForInputToGroup = (inputId, groupId, gainDb) => {
|
||||
setRouting(prev => {
|
||||
const gains = { ...prev.gains };
|
||||
const key = `in_${inputId}_${groupId}`;
|
||||
gains[key] = parseFloat(gainDb);
|
||||
return { ...prev, gains };
|
||||
});
|
||||
};
|
||||
|
||||
const setGainForGroupToOutput = (groupId, outputId, gainDb) => {
|
||||
setRouting(prev => {
|
||||
const gains = { ...prev.gains };
|
||||
const key = `${groupId}_out_${outputId}`;
|
||||
gains[key] = parseFloat(gainDb);
|
||||
return { ...prev, gains };
|
||||
});
|
||||
};
|
||||
|
||||
const formatGain = (gainDb) => {
|
||||
if (gainDb === 0) return '0dB';
|
||||
return gainDb > 0 ? `+${gainDb}dB` : `${gainDb}dB`;
|
||||
};
|
||||
|
||||
const getChannelName = (type, id) => {
|
||||
const name = channelNames?.[type]?.[id];
|
||||
return name || `${type === 'inputs' ? 'Input' : 'Output'} ${id}`;
|
||||
@@ -169,15 +202,39 @@ function AudioRoutingMatrix({ groups, channelNames }) {
|
||||
{getChannelName('inputs', i)}
|
||||
</div>
|
||||
|
||||
{groups.map(group => (
|
||||
{groups.map(group => {
|
||||
const isRouted = isInputRoutedToGroup(String(i), group.id);
|
||||
const gain = getGainForInputToGroup(String(i), group.id);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`${i}-${group.id}`}
|
||||
className={`matrix-cell ${isInputRoutedToGroup(String(i), group.id) ? 'active' : ''}`}
|
||||
className={`matrix-cell ${isRouted ? 'active' : ''}`}
|
||||
>
|
||||
<div
|
||||
className="cell-checkbox"
|
||||
onClick={() => toggleInputToGroup(String(i), group.id)}
|
||||
>
|
||||
{isInputRoutedToGroup(String(i), group.id) && <span className="checkmark">✓</span>}
|
||||
{isRouted && <span className="checkmark">✓</span>}
|
||||
</div>
|
||||
))}
|
||||
{isRouted && (
|
||||
<select
|
||||
className="gain-select"
|
||||
value={gain}
|
||||
onChange={(e) => setGainForInputToGroup(String(i), group.id, e.target.value)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<option value="-12">-12dB</option>
|
||||
<option value="-6">-6dB</option>
|
||||
<option value="-3">-3dB</option>
|
||||
<option value="0">0dB</option>
|
||||
<option value="3">+3dB</option>
|
||||
<option value="6">+6dB</option>
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
@@ -204,15 +261,39 @@ function AudioRoutingMatrix({ groups, channelNames }) {
|
||||
{group.name}
|
||||
</div>
|
||||
|
||||
{getVisibleOutputChannels().map(i => (
|
||||
{getVisibleOutputChannels().map(i => {
|
||||
const isRouted = isGroupRoutedToOutput(group.id, String(i));
|
||||
const gain = getGainForGroupToOutput(group.id, String(i));
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`${group.id}-${i}`}
|
||||
className={`matrix-cell ${isGroupRoutedToOutput(group.id, String(i)) ? 'active' : ''}`}
|
||||
className={`matrix-cell ${isRouted ? 'active' : ''}`}
|
||||
>
|
||||
<div
|
||||
className="cell-checkbox"
|
||||
onClick={() => toggleGroupToOutput(group.id, String(i))}
|
||||
>
|
||||
{isGroupRoutedToOutput(group.id, String(i)) && <span className="checkmark">✓</span>}
|
||||
{isRouted && <span className="checkmark">✓</span>}
|
||||
</div>
|
||||
))}
|
||||
{isRouted && (
|
||||
<select
|
||||
className="gain-select"
|
||||
value={gain}
|
||||
onChange={(e) => setGainForGroupToOutput(group.id, String(i), e.target.value)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<option value="-12">-12dB</option>
|
||||
<option value="-6">-6dB</option>
|
||||
<option value="-3">-3dB</option>
|
||||
<option value="0">0dB</option>
|
||||
<option value="3">+3dB</option>
|
||||
<option value="6">+6dB</option>
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user