mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-07-07 21:27:57 +02:00
UX and bones of suspected locations
This commit is contained in:
@@ -95,6 +95,7 @@ class CameraMarkersBuilder {
|
||||
LatLng? userLocation,
|
||||
int? selectedNodeId,
|
||||
void Function(OsmNode)? onNodeTap,
|
||||
bool shouldDim = false,
|
||||
}) {
|
||||
final markers = <Marker>[
|
||||
// Camera markers
|
||||
@@ -103,14 +104,14 @@ class CameraMarkersBuilder {
|
||||
.map((n) {
|
||||
// Check if this node should be highlighted (selected) or dimmed
|
||||
final isSelected = selectedNodeId == n.id;
|
||||
final shouldDim = selectedNodeId != null && !isSelected;
|
||||
final shouldDimNode = shouldDim || (selectedNodeId != null && !isSelected);
|
||||
|
||||
return Marker(
|
||||
point: n.coord,
|
||||
width: kNodeIconDiameter,
|
||||
height: kNodeIconDiameter,
|
||||
child: Opacity(
|
||||
opacity: shouldDim ? 0.5 : 1.0,
|
||||
opacity: shouldDimNode ? 0.5 : 1.0,
|
||||
child: CameraMapMarker(
|
||||
node: n,
|
||||
mapController: mapController,
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
import '../../dev_config.dart';
|
||||
import '../../models/suspected_location.dart';
|
||||
import '../suspected_location_sheet.dart';
|
||||
import '../suspected_location_icon.dart';
|
||||
|
||||
/// Smart marker widget for suspected location with single/double tap distinction
|
||||
class SuspectedLocationMapMarker extends StatefulWidget {
|
||||
final SuspectedLocation location;
|
||||
final MapController mapController;
|
||||
final void Function(SuspectedLocation)? onLocationTap;
|
||||
|
||||
const SuspectedLocationMapMarker({
|
||||
required this.location,
|
||||
required this.mapController,
|
||||
this.onLocationTap,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SuspectedLocationMapMarker> createState() => _SuspectedLocationMapMarkerState();
|
||||
}
|
||||
|
||||
class _SuspectedLocationMapMarkerState extends State<SuspectedLocationMapMarker> {
|
||||
Timer? _tapTimer;
|
||||
// From dev_config.dart for build-time parameters
|
||||
static const Duration tapTimeout = kMarkerTapTimeout;
|
||||
|
||||
void _onTap() {
|
||||
_tapTimer = Timer(tapTimeout, () {
|
||||
// Use callback if provided, otherwise fallback to direct modal
|
||||
if (widget.onLocationTap != null) {
|
||||
widget.onLocationTap!(widget.location);
|
||||
} else {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (_) => SuspectedLocationSheet(location: widget.location),
|
||||
showDragHandle: true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _onDoubleTap() {
|
||||
_tapTimer?.cancel();
|
||||
widget.mapController.move(widget.location.centroid, widget.mapController.camera.zoom + 1);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tapTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: _onTap,
|
||||
onDoubleTap: _onDoubleTap,
|
||||
child: const SuspectedLocationIcon(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper class to build marker layers for suspected locations
|
||||
class SuspectedLocationMarkersBuilder {
|
||||
static List<Marker> buildSuspectedLocationMarkers({
|
||||
required List<SuspectedLocation> locations,
|
||||
required MapController mapController,
|
||||
String? selectedLocationId,
|
||||
void Function(SuspectedLocation)? onLocationTap,
|
||||
}) {
|
||||
final markers = <Marker>[];
|
||||
|
||||
for (final location in locations) {
|
||||
if (!_isValidCoordinate(location.centroid)) continue;
|
||||
|
||||
// Check if this location should be highlighted (selected) or dimmed
|
||||
final isSelected = selectedLocationId == location.ticketNo;
|
||||
final shouldDim = selectedLocationId != null && !isSelected;
|
||||
|
||||
markers.add(
|
||||
Marker(
|
||||
point: location.centroid,
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: Opacity(
|
||||
opacity: shouldDim ? 0.5 : 1.0,
|
||||
child: SuspectedLocationMapMarker(
|
||||
location: location,
|
||||
mapController: mapController,
|
||||
onLocationTap: onLocationTap,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return markers;
|
||||
}
|
||||
|
||||
static bool _isValidCoordinate(LatLng coord) {
|
||||
return (coord.latitude != 0 || coord.longitude != 0) &&
|
||||
coord.latitude.abs() <= 90 &&
|
||||
coord.longitude.abs() <= 180;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user