fix(eq): keep valid presets when stored maps are partially corrupt
Convert the 4 EQ persistence readers (device presets, matrix presets, device names, per-station presets) to per-entry tolerant parsing via the shared persistencia_tolerante helper, so one corrupt entry no longer discards every sibling preset. The principal-preset reader gains diagnostic logging on its existing fallback path. No degraded flag or quarantine here (unlike alarms/stations) since EQ writes are explicit-only and presets are trivially re-creatable.
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:convert';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../modelos/preset_ecualizador.dart';
|
||||
import 'persistencia_tolerante.dart';
|
||||
|
||||
class ConfiguracionEcualizador {
|
||||
const ConfiguracionEcualizador({
|
||||
@@ -227,7 +228,14 @@ class ServicioEcualizador {
|
||||
await _guardarMapaStrings(prefs, _keyNombresDispositivos, nombres);
|
||||
}
|
||||
|
||||
/// Reads a `Map<String, PresetEcualizador>` from a SharedPreferences JSON key.
|
||||
/// Reads a `Map<String, PresetEcualizador>` from a SharedPreferences JSON
|
||||
/// key with per-entry tolerance (persistence-resilience D6): a value that
|
||||
/// fails to parse is skipped and logged, its sibling entries survive and
|
||||
/// every surviving key (including the matrix's colon-delimited
|
||||
/// `stationUuid:deviceId` keys) is preserved byte-for-byte. A top-level
|
||||
/// decode failure still degrades the whole map to empty (now logged too);
|
||||
/// no flag/quarantine here — EQ presets are explicit-only writes and
|
||||
/// trivially re-creatable (D6, intentional asymmetry vs. Alarms/Stations).
|
||||
Map<String, PresetEcualizador> _leerMapa(
|
||||
SharedPreferences prefs,
|
||||
String key,
|
||||
@@ -236,13 +244,21 @@ class ServicioEcualizador {
|
||||
if (raw == null || raw.isEmpty) return {};
|
||||
try {
|
||||
final data = Map<String, dynamic>.from(jsonDecode(raw) as Map);
|
||||
return data.map(
|
||||
(k, v) => MapEntry(
|
||||
k,
|
||||
PresetEcualizador.desdeJson(Map<String, dynamic>.from(v as Map)),
|
||||
final resultado = parseMapaTolerante<PresetEcualizador>(
|
||||
data,
|
||||
(valor) => PresetEcualizador.desdeJson(
|
||||
Map<String, dynamic>.from(valor as Map),
|
||||
),
|
||||
subsistema: 'ecualizador',
|
||||
coleccion: key,
|
||||
);
|
||||
return resultado.validas;
|
||||
} catch (e) {
|
||||
registrarSaltoPersistencia(
|
||||
subsistema: 'ecualizador',
|
||||
detalle: key,
|
||||
razon: e.toString(),
|
||||
);
|
||||
} catch (_) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -256,14 +272,29 @@ class ServicioEcualizador {
|
||||
await prefs.setString(key, jsonEncode(serializado));
|
||||
}
|
||||
|
||||
/// Reads a `Map<String, String>` from a SharedPreferences JSON key.
|
||||
/// Reads a `Map<String, String>` from a SharedPreferences JSON key with
|
||||
/// per-entry tolerance (persistence-resilience D6): a value that is not a
|
||||
/// String is skipped and logged, sibling entries and keys survive
|
||||
/// untouched. A top-level decode failure still degrades the whole map to
|
||||
/// empty (now logged too); no flag/quarantine here (D6).
|
||||
Map<String, String> _leerMapaStrings(SharedPreferences prefs, String key) {
|
||||
final raw = prefs.getString(key);
|
||||
if (raw == null || raw.isEmpty) return {};
|
||||
try {
|
||||
final data = Map<String, dynamic>.from(jsonDecode(raw) as Map);
|
||||
return data.map((k, v) => MapEntry(k, v as String));
|
||||
} catch (_) {
|
||||
final resultado = parseMapaTolerante<String>(
|
||||
data,
|
||||
(valor) => valor as String,
|
||||
subsistema: 'ecualizador',
|
||||
coleccion: key,
|
||||
);
|
||||
return resultado.validas;
|
||||
} catch (e) {
|
||||
registrarSaltoPersistencia(
|
||||
subsistema: 'ecualizador',
|
||||
detalle: key,
|
||||
razon: e.toString(),
|
||||
);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -276,6 +307,10 @@ class ServicioEcualizador {
|
||||
await prefs.setString(key, jsonEncode(mapa));
|
||||
}
|
||||
|
||||
/// Reads the single principal-preset key. Single-value (not a collection)
|
||||
/// so there is nothing to skip per-entry; a decode failure still falls
|
||||
/// back to [PresetEcualizador.flat] (unchanged behavior) but is now
|
||||
/// logged too (persistence-resilience D6, diagnostics).
|
||||
PresetEcualizador _leerPresetPrincipal(SharedPreferences prefs) {
|
||||
final raw = prefs.getString(_keyPresetPrincipal);
|
||||
if (raw == null || raw.isEmpty) {
|
||||
@@ -285,11 +320,20 @@ class ServicioEcualizador {
|
||||
return PresetEcualizador.desdeJson(
|
||||
Map<String, dynamic>.from(jsonDecode(raw) as Map),
|
||||
);
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
registrarSaltoPersistencia(
|
||||
subsistema: 'ecualizador',
|
||||
detalle: _keyPresetPrincipal,
|
||||
razon: e.toString(),
|
||||
);
|
||||
return PresetEcualizador.flat;
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the per-station preset map with per-entry tolerance
|
||||
/// (persistence-resilience D6) via the same shared helper as [_leerMapa];
|
||||
/// a station whose preset value fails to parse is skipped and logged, its
|
||||
/// siblings survive under their original uuid keys.
|
||||
Map<String, PresetEcualizador> _leerPresetsPorEmisora(
|
||||
SharedPreferences prefs,
|
||||
) {
|
||||
@@ -299,13 +343,21 @@ class ServicioEcualizador {
|
||||
}
|
||||
try {
|
||||
final data = Map<String, dynamic>.from(jsonDecode(raw) as Map);
|
||||
return data.map(
|
||||
(uuid, preset) => MapEntry(
|
||||
uuid,
|
||||
PresetEcualizador.desdeJson(Map<String, dynamic>.from(preset as Map)),
|
||||
final resultado = parseMapaTolerante<PresetEcualizador>(
|
||||
data,
|
||||
(valor) => PresetEcualizador.desdeJson(
|
||||
Map<String, dynamic>.from(valor as Map),
|
||||
),
|
||||
subsistema: 'ecualizador',
|
||||
coleccion: _keyPresetsPorEmisora,
|
||||
);
|
||||
return resultado.validas;
|
||||
} catch (e) {
|
||||
registrarSaltoPersistencia(
|
||||
subsistema: 'ecualizador',
|
||||
detalle: _keyPresetsPorEmisora,
|
||||
razon: e.toString(),
|
||||
);
|
||||
} catch (_) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user