FB-05: closed-loop routes in Route Planner
Add an isClosedLoop toggle to route plans (schema v3 -> v4 migration), threaded through the domain model, repository distance recomputation, the overflow menu, and the drawn polyline, so a route can loop back to its first waypoint.
This commit is contained in:
@@ -202,6 +202,8 @@ class _RoutePlannerScreenState extends ConsumerState<RoutePlannerScreen>
|
||||
Polyline(
|
||||
points: [
|
||||
for (final w in waypoints) ll.LatLng(w.latitude, w.longitude),
|
||||
if (route.isClosedLoop)
|
||||
ll.LatLng(waypoints.first.latitude, waypoints.first.longitude),
|
||||
],
|
||||
strokeWidth: 4,
|
||||
// Visibly distinct from a recorded path (see the
|
||||
@@ -315,10 +317,14 @@ class _RoutePlannerScreenState extends ConsumerState<RoutePlannerScreen>
|
||||
right: 8,
|
||||
child: _OverflowMenu(
|
||||
hasWaypoints: waypoints.isNotEmpty,
|
||||
canCloseLoop: waypoints.length >= 2,
|
||||
isClosedLoop: route.isClosedLoop,
|
||||
onRename: () => _rename(context, repo, route),
|
||||
onDownload: waypoints.isEmpty
|
||||
? null
|
||||
: () => _downloadOfflineTiles(context, waypoints),
|
||||
onToggleLoop: () =>
|
||||
repo.setClosedLoop(widget.routeId, !route.isClosedLoop),
|
||||
onDelete: () async {
|
||||
await repo.deleteRoutePlan(widget.routeId);
|
||||
widget.onBack?.call();
|
||||
@@ -509,14 +515,20 @@ class _DropPinTooltipState extends State<_DropPinTooltip>
|
||||
class _OverflowMenu extends StatelessWidget {
|
||||
const _OverflowMenu({
|
||||
required this.hasWaypoints,
|
||||
required this.canCloseLoop,
|
||||
required this.isClosedLoop,
|
||||
required this.onRename,
|
||||
required this.onDownload,
|
||||
required this.onToggleLoop,
|
||||
required this.onDelete,
|
||||
});
|
||||
|
||||
final bool hasWaypoints;
|
||||
final bool canCloseLoop;
|
||||
final bool isClosedLoop;
|
||||
final VoidCallback onRename;
|
||||
final VoidCallback? onDownload;
|
||||
final VoidCallback onToggleLoop;
|
||||
final VoidCallback onDelete;
|
||||
|
||||
@override
|
||||
@@ -528,6 +540,7 @@ class _OverflowMenu extends StatelessWidget {
|
||||
onSelected: (value) => switch (value) {
|
||||
'rename' => onRename(),
|
||||
'download' => onDownload?.call(),
|
||||
'closeLoop' => onToggleLoop(),
|
||||
'delete' => onDelete(),
|
||||
_ => null,
|
||||
},
|
||||
@@ -543,6 +556,12 @@ class _OverflowMenu extends StatelessWidget {
|
||||
enabled: hasWaypoints,
|
||||
child: const Text('Download offline tiles'),
|
||||
),
|
||||
PopupMenuItem(
|
||||
key: const Key('toggle-closed-loop'),
|
||||
value: 'closeLoop',
|
||||
enabled: canCloseLoop,
|
||||
child: Text(isClosedLoop ? 'Open the loop' : 'Close the loop'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
key: Key('delete-route'),
|
||||
value: 'delete',
|
||||
|
||||
Reference in New Issue
Block a user