fix(manifold): show active output count in drawer

This commit is contained in:
monkey-w1n5t0n 2026-07-25 14:45:04 +02:00
parent f75f683f40
commit 766493fcdc
3 changed files with 21 additions and 12 deletions

View file

@ -122,7 +122,8 @@ double-click exits). `OutputStage.tsx` is the output columns; drag a bar to set
defines `OUTPUT_MODES` = **particles** (default) / midi / osc / cv / synth / editor, each mapping to a
`BackendId`. `DEFAULT_OUTPUT_MODE='particles'`. `outputDisplayCount()` is the shared presentation
boundary for the stage and routing rows: MIDI uses its configured CC count, while backends without
a separate count present the full mode parameter set. This does not reshape the MLP or clear examples.
a separate count present the full mode parameter set. The condensed Outputs panel reports this as an
`N outputs` chip. This does not reshape the MLP or clear examples.
- `src/console/output-mode.ts`, `types.ts`, `model.ts` are the shared vocabulary — read these first
when touching anything cross-cutting:
- `types.ts`: `Focus`, `OutputMode`, `DrawerKey`, `DrawerDepth`, `FeedbackModeUI`, `SoloMode`,

View file

@ -624,6 +624,7 @@ function RoutingDrawer(ctx: ConsoleCtx, depth: DrawerDepth) {
<>
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
<Chip tone="var(--accent)">{modeDesc.label}</Chip>
<Chip>{activeParams.length} output{activeParams.length === 1 ? '' : 's'}</Chip>
<Chip tone="var(--accent)">live {counts.live || 0}</Chip>
<Chip tone="var(--accent-2)">fixed {counts.fixed || 0}</Chip>
<Chip>off {counts.off || 0}</Chip>

View file

@ -11,18 +11,25 @@ declare global {
test('output sliders follow the active backend output count', async ({ page }) => {
await loadProbe(page);
await page.evaluate(() => {
window.__mf!.setOutputMode('midi');
window.__mf!.setMidiCcCount(3);
});
await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '3');
// Drive the real UI path: output target → Outputs drawer → expanded MIDI
// config. This deliberately does not use the debug setters; the regression
// covers the same interaction an operator performs.
await page.getByTitle(/^Mode:/).click();
await page.getByRole('button', { name: 'MIDI', exact: true }).click();
await page.getByTitle('Outputs').click();
await page.getByTitle('Expand').click();
await page.getByLabel('CCs').fill('2');
await page.evaluate(() => window.__mf!.setMidiCcCount(7));
await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '7');
// The count remains visible in condensed chrome after leaving the advanced
// config, and closing the drawer reveals the same number of stage columns.
await page.getByTitle('Condense').click();
await expect(page.getByText('2 outputs', { exact: true })).toBeVisible();
await page.getByTitle('Close').click();
await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '2');
const fullCount = await page.evaluate(() => {
window.__mf!.setOutputMode('osc');
return window.__mf!.paramCount();
});
// Backends without a configured count present the full mode output set.
const fullCount = await page.evaluate(() => window.__mf!.paramCount());
await page.getByTitle(/^Mode:/).click();
await page.getByRole('button', { name: 'OSC', exact: true }).click();
await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', String(fullCount));
});