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.
This commit is contained in:
2026-04-17 17:49:25 +02:00
parent 5b4d31e2f1
commit fa3d7aa1fd

View File

@@ -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();
},
),
);
}
}