From 06d28253b7a8c63131a7ced8731c7ec2de5f2d83 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Mon, 10 Apr 2023 13:56:00 +0200 Subject: improve visibility of stops, hold btn to go 1 stop backwards, fix address not showing house addition, fix issue with route updating too many times on tap --- lib/RoutingExample.dart | 148 ++++++++++++++++++++++++------------ lib/events/NextStopLoadedEvent.dart | 7 +- lib/events/StopCompletedEvent.dart | 2 + lib/pages/navigation_page.dart | 37 +++++---- 4 files changed, 128 insertions(+), 66 deletions(-) (limited to 'lib') diff --git a/lib/RoutingExample.dart b/lib/RoutingExample.dart index ebe08b3..8aabb32 100644 --- a/lib/RoutingExample.dart +++ b/lib/RoutingExample.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:ffi'; import 'dart:math'; import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; @@ -30,6 +31,7 @@ typedef ShowDialogFunction = void Function(String title, String message); class DestinationPin { final String text; + final int sequenceNumber; final GeoCoordinates? coords; final String? postalcodeNumeric; final String? postalcodeAlpha; @@ -40,6 +42,7 @@ class DestinationPin { DestinationPin( {this.text = '', this.coords, + required this.sequenceNumber, required this.isDoublePlannedAddress, required this.postalcodeNumeric, required this.postalcodeAlpha, @@ -69,13 +72,13 @@ class RoutingExample { double currentZoom = 20; HereMapController hereMapController; StreamSubscription? stopCompletedEvent; + StreamSubscription? stopIncompletedEvent; List _routeSections = []; List _pathSections = []; List _parcelNumberPins = []; List _destinationCoords = []; List allTasks = []; - late ActiveTask activeTask; int routeSectionCursor = 0; @@ -103,8 +106,6 @@ class RoutingExample { RoutingExample(HereMapController _hereMapController) : hereMapController = _hereMapController { - activeTask = ActiveTask(0, "", 0, "", false, false); - try { _routingEngine = RoutingEngine(); } on InstantiationException { @@ -138,9 +139,15 @@ class RoutingExample { if (routeSectionCursor >= allTasks.length) { routeSectionCursor = allTasks.length - 1; } - activeTask = allTasks[routeSectionCursor]; updateHighlightedRouteSections(); - eventBus.fire(NextStopLoadedEvent()); + eventBus.fire(NextStopLoadedEvent(allTasks[routeSectionCursor])); + }); + + stopIncompletedEvent = eventBus.on().listen((e) { + routeSectionCursor -= 1; + if (routeSectionCursor < 0) routeSectionCursor = 0; + updateHighlightedRouteSections(force: true); + eventBus.fire(NextStopLoadedEvent(allTasks[routeSectionCursor])); }); blacklistProvider.getBlacklist().then((value) => {blacklist = value}); @@ -148,6 +155,7 @@ class RoutingExample { void destroy() { stopCompletedEvent?.cancel(); + stopIncompletedEvent?.cancel(); timer?.cancel(); } @@ -196,10 +204,9 @@ class RoutingExample { MapMeasure(MapMeasureKind.zoomLevel, currentZoom)); } - Widget _createWidget(String label, Color backgroundColor, + Widget _createWidget(DestinationPin pin, Color backgroundColor, {bool isDoublePlannedAddress = false}) { return Container( - padding: EdgeInsets.all(2), decoration: BoxDecoration( color: backgroundColor, borderRadius: BorderRadius.circular(10), @@ -211,11 +218,30 @@ class RoutingExample { width: 2), ), child: GestureDetector( - child: Text( - label, - style: TextStyle(fontSize: 20.0), - ), - ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all(3), + decoration: BoxDecoration( + color: Color.fromARGB(255, 0, 0, 0), + borderRadius: BorderRadius.circular(10), + shape: BoxShape.rectangle, + ), + child: Text( + pin.sequenceNumber.toString(), + style: TextStyle( + fontSize: 20.0, color: Color.fromARGB(255, 255, 255, 255)), + ), + ), + Container( + padding: EdgeInsets.all(3), + child: Text( + pin.houseNumberWithExtra ?? 'Zie pakket', + style: TextStyle(fontSize: 20.0), + ), + ), + ], + )), ); } @@ -232,6 +258,20 @@ class RoutingExample { return tasksFound.first; } +// if address is double planned and there is a stop before this one. + bool shouldShowPinOnMap(DestinationPin taskToCheck) { + for (int i = _parcelNumberPins.length - 1; i >= 0; i--) { + var item = _parcelNumberPins[i]; + if (!item.isDoublePlannedAddress) continue; + if (item == taskToCheck) return true; + if (item.coords == taskToCheck.coords && item == taskToCheck) { + return false; + } + } + + return true; + } + bool isAddressDoublePlanned(DestinationPin taskToCheck) { for (final item in _parcelNumberPins) { if (item == taskToCheck) continue; @@ -254,10 +294,11 @@ class RoutingExample { bool isFirst = true; for (final item in route.tasks!) { - debugPrint(item.deliverySequenceNumber.toString()); + //debugPrint(item.deliverySequenceNumber.toString()); if (item.addressLatitude == null || item.addressLongitude == null) { // Skip adressen die fout zijn ingegeven. + // Hier moeten we nog iets voor vinden om bestuurder te laten weten continue; } @@ -280,6 +321,7 @@ class RoutingExample { _parcelNumberPins.add( DestinationPin( + sequenceNumber: int.parse(item.deliverySequenceNumber!), text: item.deliverySequenceNumber.toString() + ' = ' + item.houseNumber! + @@ -300,16 +342,22 @@ class RoutingExample { if (item.groupSize != null) { groupLastSequenceNumber += int.parse(item.groupSize!) - 1; } + + String addrToDisplay = (item.street ?? "").toUpperCase() + + " " + + (item.houseNumber ?? "") + + (item.houseNumberAddition ?? ""); + var groupedTask = ActiveTask( sequenceNumber, item.timeframe!, groupLastSequenceNumber, - item.fullAddressForNavigation!, + addrToDisplay, item.indicationSignatureRequired == true, item.indicationNotAtNeighbours == true); if (isFirst) { - activeTask = groupedTask; + eventBus.fire(NextStopLoadedEvent(groupedTask)); isFirst = false; } allTasks.add(groupedTask); @@ -341,8 +389,6 @@ class RoutingExample { var error = routingError.toString(); } }); - - eventBus.fire(NextStopLoadedEvent()); } _showLineToHouse(Section section, GeoCoordinates houseCoords) { @@ -390,18 +436,39 @@ class RoutingExample { } } - void updateHighlightedRouteSections() { - // Show the next 20 parcel pins, to let the delivery driver decide on possible detours. + WidgetPin? createPinWidget( + DestinationPin pin, Color color, GeoCoordinates coords) { + return hereMapController.pinWidget( + _createWidget(pin, color, + isDoublePlannedAddress: pin.isDoublePlannedAddress), + coords); + } + + void updateHighlightedRouteSections({bool force = false}) { int maxPins = 300; + print('cursor ' + routeSectionCursor.toString()); + for (int i = _parcelNumberPins.length - 1; i >= 0; i--) { DestinationPin pin = _parcelNumberPins.elementAt(i); + Color color = Color.fromARGB(200, 0, 144, 138); + if (i == routeSectionCursor) color = Color.fromARGB(199, 143, 8, 31); + if (i == routeSectionCursor + 1) color = Color.fromARGB(197, 13, 36, 241); + if (destinationPinIsInBlacklist(_parcelNumberPins[i])) { + color = ui.Color.fromRGBO(143, 8, 31, 0.78); + } + + bool forceUpdateThisPin = + force && (i > routeSectionCursor - 3 && i < routeSectionCursor + 3); + if (i > routeSectionCursor + 1 && i < routeSectionCursor + maxPins) { - if (pin.pin != null) continue; - var widgetPin = hereMapController.pinWidget( - _createWidget(pin.text, Color.fromARGB(200, 0, 144, 138), - isDoublePlannedAddress: pin.isDoublePlannedAddress), - _destinationCoords[i]); + if (forceUpdateThisPin) { + pin.pin?.unpin(); + pin.pin = null; + } else if (pin.pin != null) { + continue; + } + var widgetPin = createPinWidget(pin, color, _destinationCoords[i]); widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); pin.pin = widgetPin; } else { @@ -409,30 +476,8 @@ class RoutingExample { pin.pin = null; } - // Highlight current destination. - if (i == routeSectionCursor) { - var widgetPin = hereMapController.pinWidget( - _createWidget(pin.text, ui.Color.fromARGB(199, 143, 8, 31), - isDoublePlannedAddress: pin.isDoublePlannedAddress), - _destinationCoords[i]); - widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); - pin.pin = widgetPin; - } - - if (i == routeSectionCursor + 1) { - var widgetPin = hereMapController.pinWidget( - _createWidget(pin.text, ui.Color.fromARGB(197, 13, 36, 241), - isDoublePlannedAddress: pin.isDoublePlannedAddress), - _destinationCoords[i]); - widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); - pin.pin = widgetPin; - } - - if (destinationPinIsInBlacklist(_parcelNumberPins[i])) { - var widgetPin = hereMapController.pinWidget( - _createWidget(pin.text, ui.Color.fromARGB(255, 255, 0, 234), - isDoublePlannedAddress: pin.isDoublePlannedAddress), - _destinationCoords[i]); + if (i == routeSectionCursor || i == routeSectionCursor + 1) { + var widgetPin = createPinWidget(pin, color, _destinationCoords[i]); widgetPin?.anchor = Anchor2D.withHorizontalAndVertical(0.5, 0.5); pin.pin = widgetPin; } @@ -440,6 +485,7 @@ class RoutingExample { // Show the next 5 sections as to not clutter the screen. int maxSections = 5; + int maxWalkPaths = 300; for (int i = _routeSections.length - 1; i >= 0; i--) { MapPolyline section = _routeSections.elementAt(i); MapPolyline path = _pathSections.elementAt(i); @@ -458,9 +504,13 @@ class RoutingExample { 0, 144, 138); - path.lineColor = Color.fromARGB(160, 255, 0, 0); } else { section.lineColor = Color.fromARGB(0, 255, 255, 255); + } + + if (i >= routeSectionCursor && i < routeSectionCursor + maxWalkPaths) { + path.lineColor = Color.fromARGB(160, 255, 0, 0); + } else { path.lineColor = Color.fromARGB(0, 255, 255, 255); } } diff --git a/lib/events/NextStopLoadedEvent.dart b/lib/events/NextStopLoadedEvent.dart index c4fd59d..a95e29c 100644 --- a/lib/events/NextStopLoadedEvent.dart +++ b/lib/events/NextStopLoadedEvent.dart @@ -1 +1,6 @@ -class NextStopLoadedEvent {} +import 'package:training_planner/RoutingExample.dart'; + +class NextStopLoadedEvent { + ActiveTask task; + NextStopLoadedEvent(this.task); +} diff --git a/lib/events/StopCompletedEvent.dart b/lib/events/StopCompletedEvent.dart index 8aa283b..1729307 100644 --- a/lib/events/StopCompletedEvent.dart +++ b/lib/events/StopCompletedEvent.dart @@ -1 +1,3 @@ class StopCompletedEvent {} + +class StopIncompletedEvent {} diff --git a/lib/pages/navigation_page.dart b/lib/pages/navigation_page.dart index 16494b5..59b5451 100644 --- a/lib/pages/navigation_page.dart +++ b/lib/pages/navigation_page.dart @@ -37,7 +37,7 @@ class _NavigationPageState extends State { RoutingExample? _routingExample; StreamSubscription? panGestureEvent; StreamSubscription? taskLoadedEvent; - ActiveTask? activeTask; + ActiveTask? activeTask = ActiveTask(1, "", 1, "", false, false); Future _handleLocationPermission() async { bool serviceEnabled; @@ -83,7 +83,9 @@ class _NavigationPageState extends State { }); taskLoadedEvent = eventBus.on().listen((event) { - setState(() {}); + setState(() { + activeTask = event.task; + }); }); } @@ -105,6 +107,10 @@ class _NavigationPageState extends State { eventBus.fire(StopCompletedEvent()); } + void _mockStopInComplete() { + eventBus.fire(StopIncompletedEvent()); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -114,9 +120,13 @@ class _NavigationPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - FloatingActionButton( - onPressed: () => _mockStopComplete(), - child: Icon(Icons.check_circle), + InkWell( + splashColor: Colors.blue, + onLongPress: () => _mockStopInComplete(), + child: FloatingActionButton( + onPressed: () => _mockStopComplete(), + child: Icon(Icons.check_circle), + ), ), Visibility( visible: _routingExample == null @@ -190,11 +200,9 @@ class _NavigationPageState extends State { children: [ TextSpan( text: '[' + - _routingExample!.activeTask.firstParcelNumber - .toString() + + activeTask!.firstParcelNumber.toString() + ' - ' + - _routingExample!.activeTask.lastParcelNumber - .toString() + + activeTask!.lastParcelNumber.toString() + '', style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), @@ -203,9 +211,8 @@ class _NavigationPageState extends State { ), TextSpan( text: ' ' + - (_routingExample!.activeTask.lastParcelNumber - - _routingExample! - .activeTask.firstParcelNumber + + (activeTask!.lastParcelNumber - + activeTask!.firstParcelNumber + 1) .toString(), style: TextStyle( @@ -226,7 +233,7 @@ class _NavigationPageState extends State { Padding(padding: EdgeInsets.all(5)), Expanded( child: Text( - _routingExample!.activeTask.fullAddress, + activeTask!.fullAddress, style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), fontSize: 15, @@ -239,9 +246,7 @@ class _NavigationPageState extends State { Container( height: 20, padding: EdgeInsets.only(left: 10, right: 10), - child: Row(children: [ - Text(_routingExample!.activeTask.deliveryTimeBlock) - ]), + child: Row(children: [Text(activeTask!.deliveryTimeBlock)]), ), ], ), -- cgit v1.2.3-70-g09d2