refactor(state): extract recording and search state, scope screen rebuilds
- New EstadoGrabacion owns the recording service, subscription, directory/size preferences and open-file actions - New EstadoBusqueda owns search, nearby stations, pagination and the min-bitrate filter - New orden_emisoras.dart with the OrdenEmisoras enum, shared sorter and list identity memoization so context.select comparisons work on derived lists - Large screens (inicio, buscar, favoritos, ajustes, reproductor) consume scoped selects/dedicated notifiers instead of root context.watch<EstadoRadio>, so audio buffer events no longer rebuild whole screens - Remove all 15 TODO(S4b) compat members from EstadoRadio; consumers use the dedicated providers. EstadoRadio drops from ~1121 to 753 lines, keeping playback/stations/favorites orchestration - 8 new tests including a rebuild-scoping probe (110 total green), flutter analyze clean
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import '../modelos/emisora.dart';
|
||||
|
||||
/// User-selectable ordering for every station list in the app.
|
||||
enum OrdenEmisoras { nombre, calidad }
|
||||
|
||||
/// Returns a sorted COPY of [emisoras] according to [orden].
|
||||
List<Emisora> ordenarEmisoras(List<Emisora> emisoras, OrdenEmisoras orden) {
|
||||
final ordenadas = List<Emisora>.from(emisoras);
|
||||
switch (orden) {
|
||||
case OrdenEmisoras.nombre:
|
||||
ordenadas.sort(
|
||||
(a, b) => a.nombre.toLowerCase().compareTo(b.nombre.toLowerCase()),
|
||||
);
|
||||
case OrdenEmisoras.calidad:
|
||||
ordenadas.sort((a, b) {
|
||||
final porBitrate = (b.bitrate ?? 0).compareTo(a.bitrate ?? 0);
|
||||
if (porBitrate != 0) return porBitrate;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return ordenadas;
|
||||
}
|
||||
|
||||
/// Identity-memoized derived list (S4-R5).
|
||||
///
|
||||
/// Derived-list getters used to return a fresh copy on every read, which made
|
||||
/// `context.select` rebuild on EVERY notification (lists compare by identity).
|
||||
/// This memo recomputes only when one of the source [claves] changes identity,
|
||||
/// so unrelated notifications (e.g. audio buffer events) stop rebuilding the
|
||||
/// screens that select these lists.
|
||||
class MemoLista<T> {
|
||||
List<Object?>? _claves;
|
||||
List<T>? _resultado;
|
||||
|
||||
List<T> obtener(List<Object?> claves, List<T> Function() calcular) {
|
||||
final anteriores = _claves;
|
||||
final resultado = _resultado;
|
||||
if (anteriores != null &&
|
||||
resultado != null &&
|
||||
anteriores.length == claves.length) {
|
||||
var iguales = true;
|
||||
for (var i = 0; i < claves.length; i++) {
|
||||
if (!identical(anteriores[i], claves[i])) {
|
||||
iguales = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iguales) return resultado;
|
||||
}
|
||||
final nuevo = calcular();
|
||||
_claves = List<Object?>.of(claves);
|
||||
_resultado = nuevo;
|
||||
return nuevo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user