fix(eq): split the equalizer body into 4 cards, add Restablecer a plano

Audit 11.10/11.8 (t4 lines 570-602): the prototype draws the explainer
banner, the band sliders, "Salida activa + Guardar como preset +
Restablecer a plano" and "Emisoras con ajuste propio" as 4 separate
cards. The build nested everything in one outer PluriGlassSurface, so
it read as a single merged block, and had no reset-to-flat action at
all.

Removes the outer wrapper from _CuerpoEcualizador. EcualizadorWidget
already draws its own card (design ADR-5, unchanged); the explainer
banner already has its own tinted background (unchanged); "Emisoras
con ajuste propio" now wraps itself in its own PluriGlassSurface; a
new _TarjetaSalidaYAcciones groups Salida activa with two tappable
rows — "Guardar como preset" (relocated from a floating end-aligned
button) and the new "Restablecer a plano", which applies
PresetEcualizador.flat via the existing EstadoEcualizador.cambiarPreset
— the same call the "Plano" preset chip already makes, not a new
capability.

The 5-slider band count, servicio_ecualizador.dart and
preset_ecualizador.dart are untouched.
This commit is contained in:
2026-07-30 00:57:29 +02:00
parent e5d461af53
commit 653848899f
29 changed files with 373 additions and 96 deletions
@@ -9,6 +9,8 @@ import 'package:pluriwave/modelos/dispositivo_audio.dart';
import 'package:pluriwave/modelos/emisora.dart';
import 'package:pluriwave/modelos/preset_ecualizador.dart';
import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_ecualizador.dart';
import 'package:pluriwave/widgets/ecualizador_widget.dart';
import 'package:pluriwave/widgets/pluri_glass_surface.dart';
import 'package:pluriwave/widgets/pluri_push_scaffold.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -249,6 +251,12 @@ void main() {
equals('2'),
);
// Item 19's 4-card restructure made the page taller — the row now
// sits below the default 800x600 test viewport.
await tester.ensureVisible(
find.byKey(const Key('eq-stations-own-eq-row')),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('eq-stations-own-eq-row')));
await tester.pumpAndSettle();
@@ -270,6 +278,12 @@ void main() {
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
// Item 19's 4-card restructure made the page taller — the row now
// sits below the default 800x600 test viewport.
await tester.ensureVisible(
find.byKey(const Key('eq-stations-own-eq-row')),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('eq-stations-own-eq-row')));
await tester.pumpAndSettle();
@@ -340,6 +354,99 @@ void main() {
},
);
testWidgets('visual fidelity (audit 11.10): the explainer banner and the '
'stations-with-own-EQ row are SEPARATE cards, not one shared glass '
'surface', (tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
final explainerCard = find.ancestor(
of: find.byKey(const Key('eq-base-explainer-banner')),
matching: find.byType(PluriGlassSurface),
);
expect(
find.descendant(
of: explainerCard,
matching: find.byKey(const Key('eq-stations-own-eq-row')),
),
findsNothing,
reason:
't4 lines 571/600-602: the prototype draws these as 2 of 4 '
'separate cards, not one merged block',
);
// EcualizadorWidget already wraps itself in its own PluriGlassSurface
// (design ADR-5) — this stays true once the OUTER wrapper is gone.
expect(
find.descendant(
of: find.byType(EcualizadorWidget),
matching: find.byType(PluriGlassSurface),
),
findsOneWidget,
);
});
testWidgets(
'visual fidelity (audit 11.8): Salida activa, Guardar como preset and '
'Restablecer a plano are grouped into ONE card',
(tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
final outputCard = find.ancestor(
of: find.byKey(const Key('eq-active-output-row')),
matching: find.byType(PluriGlassSurface),
);
expect(outputCard, findsOneWidget);
expect(
find.descendant(
of: outputCard,
matching: find.byKey(const Key('eq-save-preset-action')),
),
findsOneWidget,
reason: 't4 lines 592-598: one grouped card for all 3 rows',
);
expect(
find.descendant(
of: outputCard,
matching: find.byKey(const Key('eq-reset-flat-action')),
),
findsOneWidget,
);
},
);
testWidgets(
'visual fidelity (audit 11.8): tapping Restablecer a plano resets the '
'active preset to Flat',
(tester) async {
_suppressListTileInkAssertion();
final estado = await crearEstado();
addTearDown(estado.dispose);
await estado.ecualizador.cambiarPreset(PresetEcualizador.rock);
expect(estado.ecualizador.presetActual, PresetEcualizador.rock);
await tester.pumpWidget(buildScreen(estado));
await tester.pumpAndSettle();
await tester.ensureVisible(
find.byKey(const Key('eq-reset-flat-action')),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('eq-reset-flat-action')));
await tester.pumpAndSettle();
expect(estado.ecualizador.presetActual, PresetEcualizador.flat);
},
);
testWidgets(
'Guardar como preset with a whitespace-only name shows the same validation message',
(tester) async {