From 919ee55c45bc9615d64173ec69f30636b0b09467 Mon Sep 17 00:00:00 2001 From: JulianAlcala Date: Fri, 17 Apr 2026 17:49:25 +0200 Subject: [PATCH] fix(location): keep map visible on transient network errors Show snackbar instead of replacing the entire map with an error state when a reload fails. Only show RefreshableErrorState on first load failure. --- .../presentation/location_screen.dart | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart index 7290445f..9ba5207e 100644 --- a/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart +++ b/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart @@ -85,52 +85,66 @@ class LocationScreen extends ConsumerWidget { }, ); + ref.listen(controlPanelViewModelProvider, (previous, next) { + if (next.hasError && previous != null && !previous.hasError) { + showTopSnackbar( + context, + message: context.translate(I18n.errorGeneric), + type: MessageType.error, + ); + } + }); + + ref.listen(locationViewModelProvider, (previous, next) { + if (next.hasError && previous != null && !previous.hasError) { + showTopSnackbar( + context, + message: context.translate(I18n.errorGeneric), + type: MessageType.error, + ); + } + }); + + final controlPanelState = asyncControlPanelState.value; + final locationState = asyncLocationState.value; + final isLoading = asyncControlPanelState.isLoading && + controlPanelState == null; + return LegacyPageLayout( theme: theme, title: context.translate(I18n.mapTitle), showBack: false, - body: asyncControlPanelState.when( - skipLoadingOnReload: true, - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, _) => RefreshableErrorState( - onRefresh: () async { - ref.invalidate(controlPanelViewModelProvider); - ref.invalidate(locationViewModelProvider); - await ref.read(controlPanelViewModelProvider.future); - }, - ), - data: (controlPanelState) => asyncLocationState.when( - skipLoadingOnReload: true, - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, _) => RefreshableErrorState( - onRefresh: () async { - ref.invalidate(locationViewModelProvider); - await ref.read(locationViewModelProvider.future); - }, - ), - data: (locationState) => LocationMap( - selectedPosition: controlPanelState.selectedPosition, - selectedDevice: controlPanelState.selectedDevice, - devices: controlPanelState.devices, - positions: controlPanelState.positions, - geofences: locationState.geofences, - frequentPlaces: locationState.frequentPlaces, - positionHistory: locationState.positionHistory, - showRouteTrail: locationState.showRouteTrail, - isLoadingHistory: locationState.isLoadingHistory, - onDeviceChanged: (device) { - ref - .read(controlPanelViewModelProvider.notifier) - .setSelectedDevice(device); - }, - onRefreshPosition: () { - ref - .read(controlPanelViewModelProvider.notifier) - .refreshPositions(); - }, - ), - ), - ), + body: isLoading + ? const Center(child: CircularProgressIndicator()) + : controlPanelState == null + ? RefreshableErrorState( + onRefresh: () async { + ref.invalidate(controlPanelViewModelProvider); + ref.invalidate(locationViewModelProvider); + await ref.read(controlPanelViewModelProvider.future); + }, + ) + : LocationMap( + selectedPosition: controlPanelState.selectedPosition, + selectedDevice: controlPanelState.selectedDevice, + devices: controlPanelState.devices, + positions: controlPanelState.positions, + geofences: locationState?.geofences ?? const [], + frequentPlaces: locationState?.frequentPlaces ?? const [], + positionHistory: locationState?.positionHistory ?? const [], + showRouteTrail: locationState?.showRouteTrail ?? false, + isLoadingHistory: locationState?.isLoadingHistory ?? false, + onDeviceChanged: (device) { + ref + .read(controlPanelViewModelProvider.notifier) + .setSelectedDevice(device); + }, + onRefreshPosition: () { + ref + .read(controlPanelViewModelProvider.notifier) + .refreshPositions(); + }, + ), ); } }