diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/route_history_layer.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/route_history_layer.dart index 45368b18..478a3f59 100644 --- a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/route_history_layer.dart +++ b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/route_history_layer.dart @@ -3,17 +3,18 @@ import 'dart:math' as math; import 'package:control_panel/control_panel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:intl/intl.dart'; import 'package:latlong2/latlong.dart'; const _clusterBaseDegrees = 0.5; const _clusterBaseZoom = 8; +const routeColor = Color(0xFF329E95); +const routeArrowColor = Color(0xFFFF6D00); const routeStartColor = Color(0xFF4CAF50); - -bool _hasValidCoords(PositionEntity p) => p.latitude != 0 || p.longitude != 0; const routeEndColor = Color(0xFFF44336); -Color routeGradient(double t) => Color.lerp(routeStartColor, routeEndColor, t)!; +bool _hasValidCoords(PositionEntity p) => p.latitude != 0 || p.longitude != 0; class RouteHistoryLayer extends StatelessWidget { final List positionHistory; @@ -39,24 +40,16 @@ class RouteHistoryLayer extends StatelessWidget { List buildRouteSegments() { if (positionHistory.length < 2) return []; - final segments = []; - for (int i = 0; i < positionHistory.length - 1; i++) { - final t = i / (positionHistory.length - 1); - segments.add( - Polyline( - points: [ - LatLng(positionHistory[i].latitude, positionHistory[i].longitude), - LatLng( - positionHistory[i + 1].latitude, - positionHistory[i + 1].longitude, - ), - ], - color: routeGradient(t), - strokeWidth: 4.0, - ), - ); - } - return segments; + final points = positionHistory + .where(_hasValidCoords) + .map((p) => LatLng(p.latitude, p.longitude)) + .toList(); + + if (points.length < 2) return []; + + return [ + Polyline(points: points, color: routeColor, strokeWidth: 4.0), + ]; } List _buildDirectionArrows() { @@ -66,26 +59,27 @@ class RouteHistoryLayer extends StatelessWidget { for (int i = 0; i < positionHistory.length - 1; i++) { final from = positionHistory[i]; final to = positionHistory[i + 1]; - if (!_hasValidCoords(from)) continue; - if (!_hasValidCoords(to)) continue; + if (!_hasValidCoords(from) || !_hasValidCoords(to)) continue; final midLat = (from.latitude + to.latitude) / 2; final midLng = (from.longitude + to.longitude) / 2; - final angle = math.atan2( + final bearing = math.atan2( to.longitude - from.longitude, to.latitude - from.latitude, ); - final t = i / (positionHistory.length - 1); - arrows.add( Marker( point: LatLng(midLat, midLng), - width: 16, - height: 16, + width: 18, + height: 18, child: Transform.rotate( - angle: -angle, - child: Icon(Icons.navigation, color: routeGradient(t), size: 16), + angle: bearing, + child: const Icon( + Icons.navigation, + color: routeArrowColor, + size: 18, + ), ), rotate: false, ), @@ -149,18 +143,17 @@ class RouteHistoryLayer extends StatelessWidget { for (final cluster in clustered) { final firstIdx = cluster.first; final position = intermediates[firstIdx]; - final originalIdx = firstIdx + 1; - final t = originalIdx / (positionHistory.length - 1); - final color = routeGradient(t); if (cluster.length == 1) { - markers.add(_buildIntermediateMarker(position: position, color: color)); + markers.add( + _buildIntermediateMarker(position: position, color: routeColor), + ); } else { markers.add( _buildClusterMarker( position: position, count: cluster.length, - color: color, + color: routeColor, ), ); } @@ -174,16 +167,41 @@ class RouteHistoryLayer extends StatelessWidget { required Color color, required IconData icon, }) { + final time = DateFormat.Hm().format( + DateTime.fromMillisecondsSinceEpoch(position.createdAt), + ); + return Marker( point: LatLng(position.latitude, position.longitude), - width: 32, - height: 32, + width: 64, + height: 52, child: GestureDetector( onTap: () => onPositionTap(position), - child: _CircleMarkerIcon( - color: color, - size: 32, - child: Icon(icon, color: Colors.white, size: 18), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _CircleMarkerIcon( + color: color, + size: 32, + child: Icon(icon, color: Colors.white, size: 18), + ), + const SizedBox(height: 2), + Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + time, + style: const TextStyle( + color: Colors.white, + fontSize: 9, + fontWeight: FontWeight.w700, + ), + ), + ), + ], ), ), rotate: true, diff --git a/modules/legacy/modules/location/pubspec.yaml b/modules/legacy/modules/location/pubspec.yaml index 367dfd3c..b8eafe67 100644 --- a/modules/legacy/modules/location/pubspec.yaml +++ b/modules/legacy/modules/location/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: flutter_svg: ^2.2.2 uuid: ^4.5.3 share_plus: ^10.1.4 + intl: ^0.20.2 dev_dependencies: flutter_test: