ente/lib/ui/map/map_view.dart
2023-06-05 05:47:38 +05:30

160 lines
4.7 KiB
Dart

import "dart:async";
import "package:flutter/material.dart";
import "package:flutter_map/flutter_map.dart";
import "package:flutter_map_marker_cluster/flutter_map_marker_cluster.dart";
import "package:latlong2/latlong.dart";
import "package:photos/ui/map/image_marker.dart";
import "package:photos/ui/map/map_button.dart";
import 'package:photos/ui/map/map_gallery_tile.dart';
import 'package:photos/ui/map/map_gallery_tile_badge.dart';
import "package:photos/ui/map/map_marker.dart";
class MapView extends StatefulWidget {
final List<ImageMarker> imageMarkers;
final Function updateVisibleImages;
final MapController controller;
const MapView({
Key? key,
required this.updateVisibleImages,
required this.imageMarkers,
required this.controller,
}) : super(key: key);
@override
State<StatefulWidget> createState() => _MapViewState();
}
class _MapViewState extends State<MapView> {
Timer? _debounceTimer;
LatLng center = LatLng(10.732951, 78.405635);
bool _isDebouncing = false;
void _onPositionChanged(position, hasGesture) {
if (position.bounds != null) {
if (!_isDebouncing) {
_isDebouncing = true;
_debounceTimer?.cancel(); // Cancel previous debounce timer
_debounceTimer = Timer(const Duration(milliseconds: 200), () {
widget.updateVisibleImages(position.bounds!);
_isDebouncing = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
FlutterMap(
mapController: widget.controller,
options: MapOptions(
center: center,
zoom: 3,
minZoom: 1,
maxZoom: 16.5,
onPositionChanged: _onPositionChanged,
plugins: [
MarkerClusterPlugin(),
],
),
layers: [
TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
),
MarkerClusterLayerOptions(
maxClusterRadius: 100,
showPolygon: true,
size: const Size(75, 75),
fitBoundsOptions: const FitBoundsOptions(
padding: EdgeInsets.all(1),
),
markers: widget.imageMarkers.asMap().entries.map((marker) {
final imageMarker = marker.value;
return mapMarker(imageMarker, marker.key.toString());
}).toList(),
polygonOptions: const PolygonOptions(
borderColor: Colors.green,
color: Colors.transparent,
borderStrokeWidth: 1,
),
builder: (context, markers) {
final index = int.parse(
markers.first.key
.toString()
.replaceAll(RegExp(r'[^0-9]'), ''),
);
return Stack(
children: [
MapGalleryTile(
key: Key(markers.first.key.toString()),
imageMarker: widget.imageMarkers[index],
),
MapGalleryTileBadge(size: markers.length)
],
);
},
),
],
),
Positioned(
bottom: 10,
left: 10,
child: MapButton(
icon: Icons.my_location,
onPressed: () {
widget.controller.move(
center,
widget.controller.zoom,
);
},
heroTag: 'location',
),
),
Positioned(
top: 10,
left: 10,
child: MapButton(
icon: Icons.arrow_back,
onPressed: () {
Navigator.pop(context);
},
heroTag: 'back',
),
),
Positioned(
bottom: 10,
right: 10,
child: Column(
children: [
MapButton(
icon: Icons.add,
onPressed: () {
widget.controller.move(
widget.controller.center,
widget.controller.zoom + 1,
);
},
heroTag: 'zoom-in',
),
MapButton(
icon: Icons.remove,
onPressed: () {
widget.controller.move(
widget.controller.center,
widget.controller.zoom - 1,
);
},
heroTag: 'zoom-out',
),
],
),
),
],
);
}
}