fix(eq): seed device ID at startup and add device management UI
Fix multi-device EQ auto-switching by calling obtenerDispositivoActual() during cargarPersistido() to seed the initial device ID. Add device management modal with rename support, EQ preset editing, and connection status indicator. Translate device UI keys to all 13 locales.
This commit is contained in:
@@ -8,6 +8,7 @@ import 'package:pluriwave/estado/estado_grabacion.dart';
|
||||
import 'package:pluriwave/estado/estado_idioma.dart';
|
||||
import 'package:pluriwave/estado/estado_radio.dart';
|
||||
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
||||
import 'package:pluriwave/modelos/dispositivo_audio.dart';
|
||||
import 'package:pluriwave/modelos/preset_ecualizador.dart';
|
||||
import 'package:pluriwave/pantallas/pantalla_ajustes.dart';
|
||||
import 'package:pluriwave/servicios/servicio_grabacion_radio.dart';
|
||||
@@ -92,6 +93,42 @@ void main() {
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 100));
|
||||
}
|
||||
|
||||
// Also update crearEstado to support nombresDispositivos
|
||||
Future<EstadoRadio> crearEstadoConNombres({
|
||||
bool eqMultiDeviceEnabled = true,
|
||||
Map<String, PresetEcualizador>? presetsDispositivo,
|
||||
Map<String, String>? nombresDispositivos,
|
||||
String? activeDeviceId,
|
||||
}) async {
|
||||
final fakeDispositivo = activeDeviceId != null
|
||||
? (FakeServicioDispositivoAudio()
|
||||
..emitirDispositivo(
|
||||
DispositivoAudio(
|
||||
id: activeDeviceId,
|
||||
tipo: TipoDispositivo.bluetoothA2dp,
|
||||
nombre: 'BT Speaker',
|
||||
),
|
||||
))
|
||||
: null;
|
||||
final estado = EstadoRadio(
|
||||
audio: FakeServicioAudio(),
|
||||
favoritos: FakeServicioFavoritos(),
|
||||
radio: FakeServicioRadio(),
|
||||
servicioEcualizador: FakeServicioEcualizador(
|
||||
eqMultiDeviceEnabled: eqMultiDeviceEnabled,
|
||||
presetsDispositivo: presetsDispositivo ??
|
||||
{'bt_a2dp:AA:BB': PresetEcualizador.rock},
|
||||
nombresDispositivos: nombresDispositivos ?? {},
|
||||
),
|
||||
servicioGrabacion: _FakeGrabacion(),
|
||||
resolverArchivoCustom: _archivoCustomVacio,
|
||||
iniciarAutomaticamente: false,
|
||||
dispositivoAudio: fakeDispositivo,
|
||||
);
|
||||
await estado.ecualizador.cargarPersistido();
|
||||
return estado;
|
||||
}
|
||||
|
||||
// ── Phase 7 tests ──────────────────────────────────────────────────────────
|
||||
|
||||
group('_SeccionEcualizadorAvanzado (Phase 7)', () {
|
||||
@@ -194,6 +231,155 @@ void main() {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// ── Phase 3 (eq-device-autoswitch-ux): connection indicator + modal ──────────
|
||||
|
||||
group('SeccionEcualizadorAvanzado connection indicator Phase 3', () {
|
||||
// 3.1 RED — active device row shows green connection dot
|
||||
testWidgets('3.1 active device row shows green connection indicator', (tester) async {
|
||||
setLargeSurface(tester);
|
||||
_suppressListTileInkAssertion();
|
||||
const activeId = 'bt_a2dp:AA:BB';
|
||||
final estado = await crearEstadoConNombres(
|
||||
eqMultiDeviceEnabled: true,
|
||||
presetsDispositivo: {
|
||||
activeId: PresetEcualizador.rock,
|
||||
'wired_headset': PresetEcualizador.jazz,
|
||||
},
|
||||
activeDeviceId: activeId,
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await tester.pumpWidget(buildAjustes(estado));
|
||||
await pumpStable(tester);
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('Known audio devices'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).first,
|
||||
);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Green connection dot should be present (Icon with green color for active device)
|
||||
final greenIcons = tester.widgetList<Icon>(find.byType(Icon)).where(
|
||||
(icon) => icon.color == Colors.green,
|
||||
);
|
||||
// At least one green icon present
|
||||
expect(greenIcons, isNotEmpty);
|
||||
});
|
||||
|
||||
// 3.2 RED — tapping device row opens bottom sheet with TextField and EcualizadorWidget
|
||||
testWidgets('3.2 tapping device row opens modal with TextField', (tester) async {
|
||||
setLargeSurface(tester);
|
||||
_suppressListTileInkAssertion();
|
||||
final estado = await crearEstadoConNombres(
|
||||
presetsDispositivo: {'bt_a2dp:AA:BB': PresetEcualizador.rock},
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await tester.pumpWidget(buildAjustes(estado));
|
||||
await pumpStable(tester);
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('Known audio devices'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).first,
|
||||
);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Tap the device row (tap the edit icon or the row itself)
|
||||
final editIcons = find.byIcon(Icons.edit_rounded);
|
||||
expect(editIcons, findsWidgets);
|
||||
await tester.tap(editIcons.first);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Bottom sheet should appear with a TextField
|
||||
expect(find.byType(TextField), findsWidgets);
|
||||
});
|
||||
|
||||
// 3.6 RED — renaming in modal and confirming calls renombrarDispositivo
|
||||
testWidgets('3.6 confirming rename in modal updates device name', (tester) async {
|
||||
setLargeSurface(tester);
|
||||
_suppressListTileInkAssertion();
|
||||
const deviceId = 'bt_a2dp:AA:BB';
|
||||
final estado = await crearEstadoConNombres(
|
||||
presetsDispositivo: {deviceId: PresetEcualizador.rock},
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await tester.pumpWidget(buildAjustes(estado));
|
||||
await pumpStable(tester);
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('Known audio devices'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).first,
|
||||
);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Open modal
|
||||
await tester.tap(find.byIcon(Icons.edit_rounded).first);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Enter a new name
|
||||
final textField = find.byType(TextField).first;
|
||||
await tester.enterText(textField, 'My Living Room Speaker');
|
||||
await pumpStable(tester);
|
||||
|
||||
// Tap confirm/save button
|
||||
final saveButton = find.byIcon(Icons.save_rounded);
|
||||
expect(saveButton, findsWidgets);
|
||||
await tester.tap(saveButton.first);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Device should now have the new name
|
||||
expect(
|
||||
estado.ecualizador.obtenerNombreDispositivo(deviceId),
|
||||
equals('My Living Room Speaker'),
|
||||
);
|
||||
});
|
||||
|
||||
// 3.7 RED — dismissing modal without confirming leaves name unchanged
|
||||
testWidgets('3.7 dismissing modal without confirming leaves name unchanged', (tester) async {
|
||||
setLargeSurface(tester);
|
||||
_suppressListTileInkAssertion();
|
||||
const deviceId = 'bt_a2dp:AA:BB';
|
||||
final estado = await crearEstadoConNombres(
|
||||
presetsDispositivo: {deviceId: PresetEcualizador.rock},
|
||||
nombresDispositivos: {deviceId: 'Original Name'},
|
||||
);
|
||||
addTearDown(estado.dispose);
|
||||
|
||||
await tester.pumpWidget(buildAjustes(estado));
|
||||
await pumpStable(tester);
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('Known audio devices'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).first,
|
||||
);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Open modal
|
||||
await tester.tap(find.byIcon(Icons.edit_rounded).first);
|
||||
await pumpStable(tester);
|
||||
|
||||
// Change the text but do NOT confirm
|
||||
final textField = find.byType(TextField).first;
|
||||
await tester.enterText(textField, 'New Name Not Saved');
|
||||
await pumpStable(tester);
|
||||
|
||||
// Dismiss by pressing back/escape
|
||||
await tester.tapAt(const Offset(100, 100)); // tap outside bottom sheet
|
||||
await pumpStable(tester);
|
||||
|
||||
// Name should remain unchanged
|
||||
expect(
|
||||
estado.ecualizador.obtenerNombreDispositivo(deviceId),
|
||||
equals('Original Name'),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ── Infrastructure ──────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user