|
|
|
|
@ -117,6 +117,57 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// "View" button: loads the floor map (if a floor is selected) or the building outline.
|
|
|
|
|
Future<void> _onViewPressed(AssetTrackingProvider provider) async {
|
|
|
|
|
expansibleController.collapse();
|
|
|
|
|
provider.coordinates = [];
|
|
|
|
|
provider.assetsOnTheFloorList = [];
|
|
|
|
|
provider.notify();
|
|
|
|
|
|
|
|
|
|
provider.getAssetsFromPenguinByFloor();
|
|
|
|
|
|
|
|
|
|
if (provider.selectedFloor != null) {
|
|
|
|
|
getFloorMap(provider.selectedFloor!.id!);
|
|
|
|
|
provider.getZoneFromPenguin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Building only: remove any previously displayed floor map so the building outline is visible.
|
|
|
|
|
setState(() {
|
|
|
|
|
_geojson = null;
|
|
|
|
|
floorMapModel = null;
|
|
|
|
|
_selectedZoneProperties = null;
|
|
|
|
|
markers = [];
|
|
|
|
|
_lastFittedCoordinatesKey = null; // force re-fit even if the same building is viewed again
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Utils.showLoading(context);
|
|
|
|
|
await provider.getZoneFromPenguin();
|
|
|
|
|
if (!mounted) return;
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|
// Camera fit happens in the building-outline Selector once the polygon is rendered.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Signature of the last building outline the camera was fitted to.
|
|
|
|
|
String? _lastFittedCoordinatesKey;
|
|
|
|
|
|
|
|
|
|
/// Zooms/pans the map so all [points] are visible. Runs after the current frame so the
|
|
|
|
|
/// map has its final size, and schedules a frame so the callback is guaranteed to fire.
|
|
|
|
|
void _fitCameraToPoints(List<LatLng> points) {
|
|
|
|
|
if (points.isEmpty) return;
|
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
|
if (!mounted) return;
|
|
|
|
|
if (points.length == 1) {
|
|
|
|
|
mapController.move(points.first, 18);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mapController.fitCamera(
|
|
|
|
|
CameraFit.bounds(bounds: LatLngBounds.fromPoints(points), padding: const EdgeInsets.all(48), maxZoom: 20),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
WidgetsBinding.instance.scheduleFrame();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onFloorMapLoaded(FloorMapModel? loadedFloorMap) {
|
|
|
|
|
floorMapModel = loadedFloorMap;
|
|
|
|
|
_selectedZoneProperties = null;
|
|
|
|
|
@ -409,13 +460,22 @@ class _MapTrackingPageState extends State<MapTrackingPage> {
|
|
|
|
|
],
|
|
|
|
|
if (inAppView && _geojson == null)
|
|
|
|
|
Selector<AssetTrackingProvider, List<Coordinates>>(
|
|
|
|
|
selector: (_, assetTPro) => assetTPro.coordinates,
|
|
|
|
|
selector: (_, assetTPro) => List<Coordinates>.of(assetTPro.coordinates),
|
|
|
|
|
builder: (_, coordinates, __) {
|
|
|
|
|
if (coordinates.isEmpty) return const SizedBox();
|
|
|
|
|
|
|
|
|
|
List<LatLng> list = [
|
|
|
|
|
for (var coordinate in (coordinates)) LatLng(coordinate.latitude!, coordinate.longitude!),
|
|
|
|
|
for (var coordinate in (coordinates))
|
|
|
|
|
if (coordinate.latitude != null && coordinate.longitude != null) LatLng(coordinate.latitude!, coordinate.longitude!),
|
|
|
|
|
];
|
|
|
|
|
if (list.isEmpty) return const SizedBox();
|
|
|
|
|
|
|
|
|
|
// Fit the camera to the building outline once per new outline.
|
|
|
|
|
final key = "${assetTrackingProvider.selectedBuilding?.id}|${list.length}|${list.first}|${list.last}";
|
|
|
|
|
if (key != _lastFittedCoordinatesKey) {
|
|
|
|
|
_lastFittedCoordinatesKey = key;
|
|
|
|
|
_fitCameraToPoints(list);
|
|
|
|
|
}
|
|
|
|
|
List<Polygon> zonesPolygons = [
|
|
|
|
|
Polygon(
|
|
|
|
|
label: assetTrackingProvider.selectedBuilding?.label ?? "",
|
|
|
|
|
|