diff --git a/lib/consts.dart b/lib/consts.dart index 43f1286..b5d636d 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -9,7 +9,7 @@ class TTConsts { static get SESSION_SERVER => "https://api.zontreck.com/timetrack/$UPDATE_CHANNEL/timetrack.php"; - static const VERSION = "1.0.0-beta.34"; + static const VERSION = "1.0.0-beta.35"; static bool UPDATE_AVAILABLE = false; static UpdateChannel UPDATE_CHANNEL = UpdateChannel.beta; diff --git a/lib/data.dart b/lib/data.dart index 446dda1..00329e0 100644 --- a/lib/data.dart +++ b/lib/data.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; @@ -31,7 +33,7 @@ class SessionData { static List Trips = []; - static Delivery? currentDelivery; + //static Delivery? currentDelivery; static Trip? currentTrip; static List positions = []; static late StreamSubscription _listener; @@ -74,6 +76,7 @@ class SessionData { int total = 0; for (var trip in Trips) { total += trip.deliveries.length; + total += trip.DropOffLocations.length; } return total; @@ -302,7 +305,7 @@ class SessionData { static Future Logout() async { IsOnTheClock = false; - currentDelivery = null; + //currentDelivery = null; currentTrip = null; _listener.cancel(); @@ -409,7 +412,7 @@ class SessionData { IsOnTheClock = false; StartTime = DateTime.fromMillisecondsSinceEpoch(0); Trips = []; - currentDelivery = null; + //currentDelivery = null; currentTrip = null; positions = []; EndTime = DateTime.fromMillisecondsSinceEpoch(0); @@ -454,7 +457,7 @@ class SessionData { if (DirtyState) { DirtyState = false; - DisplayMessage = "Saved cache state"; + //DisplayMessage = "Saved cache state"; } } @@ -504,10 +507,6 @@ class SessionData { currentTrip = Trips.last; } - if (ct.containsKey("current_delivery")) { - currentDelivery = currentTrip!.deliveries.last; - } - print("Deserialized data: ${SnbtIo.writeToString(ct)}"); } @@ -542,13 +541,8 @@ class SessionData { } ct.put("trips", myTrips); - // This format supports saving current trip and current delivery. - if (currentDelivery != null) { - ct.put("current_delivery", await currentDelivery!.toNBT()); - } - if (currentTrip != null) { - ct.put("current_trip", await currentTrip!.toNBT()); + NbtUtils.writeBoolean(ct, "current_trip", true); } if (TotalPay != null) { @@ -673,11 +667,11 @@ class SessionData { return currentTrip!; } - static Delivery GetNewDelivery() { + static Future DropOffCompleted() async { if (currentTrip != null) { - var dropOff = currentTrip!.startNewDelivery(); - currentDelivery = dropOff; - return dropOff; + currentTrip!.DropOffLocations.add( + SmallPosition.fromPosition(await GetNewLocation()), + ); } else { throw Exception("A delivery cannot exist without a trip"); } @@ -687,7 +681,6 @@ class SessionData { if (currentTrip != null) { currentTrip!.EndTime = DateTime.now(); } - currentDelivery = null; currentTrip = null; } @@ -729,6 +722,10 @@ class SessionData { } } +@Deprecated( + "This struct is left here for legacy compatibility. It is not used anymore.", +) +/// This struct is left here for legacy compatibility. It is not used anymore. class Delivery { SmallPosition? endLocation; DateTime StartTime = DateTime.now(); @@ -787,7 +784,12 @@ class Delivery { } class Trip { + @Deprecated( + "The old Deliveries struct has been deprecated. Please use DropOffLocations instead.", + ) + /// The old Deliveries struct has been deprecated. Please use DropOffLocations instead. List deliveries = []; + List DropOffLocations = []; DateTime StartTime = DateTime(0); DateTime EndTime = DateTime(0); @@ -796,13 +798,6 @@ class Trip { StartTime = DateTime.now(); } - Delivery startNewDelivery() { - var delivery = Delivery(); - deliveries.add(delivery); - - return delivery; - } - Map toJsonMap() { Map trip = { "start": StartTime.toIso8601String(), @@ -813,7 +808,9 @@ class Trip { dropOffs.add(delivery.toJsonMap()); } - trip["deliveries"] = dropOffs; + if (deliveries.isNotEmpty) trip["deliveries"] = dropOffs; + // if(DropOffLocations.isNotEmpty) + // trip["dropoffs"] = []; return trip; } @@ -845,10 +842,17 @@ class Trip { } ListTag drops = ListTag(); - for (var drop in deliveries) { - drops.add(await drop.toNBT()); + if (deliveries.isNotEmpty) { + for (var drop in deliveries) { + drops.add(await drop.toNBT()); + } + ct.put("deliveries", drops); + } else { + for (var drop in DropOffLocations) { + drops.add(await drop.toNBT()); + } + ct.put("dropOffs", drops); } - ct.put("deliveries", drops); return ct; } @@ -864,12 +868,19 @@ class Trip { trip.EndTime = DateTime.parse(tag.get("end")!.asString()); } - ListTag drops = tag.get("deliveries")! as ListTag; - for (var drop in drops.value) { - Delivery del = await Delivery.fromNBT(drop.asCompoundTag()); - trip.deliveries.add(del); + if (tag.containsKey("deliveries")) { + ListTag drops = tag.get("deliveries")! as ListTag; + for (var drop in drops.value) { + Delivery del = await Delivery.fromNBT(drop.asCompoundTag()); + trip.deliveries.add(del); + } + } else if (tag.containsKey("dropOffs")) { + ListTag drops = tag.get("dropOffs")! as ListTag; + for (var drop in drops.value) { + SmallPosition pos = await SmallPosition.fromNBT(drop.asCompoundTag()); + trip.DropOffLocations.add(pos); + } } - return trip; } } diff --git a/lib/pages/HomePage.dart b/lib/pages/HomePage.dart index dc61513..a861ff7 100644 --- a/lib/pages/HomePage.dart +++ b/lib/pages/HomePage.dart @@ -223,7 +223,7 @@ class _HomePageState extends State { onPressed: () { Navigator.pop(context); - SessionData.currentDelivery!.MarkEndLocation(); + //SessionData.currentDelivery!.MarkEndLocation(); SessionData.EndTrip(); @@ -254,24 +254,36 @@ class _HomePageState extends State { Widget GetDeliveryWidgets() { return Column( children: [ - ElevatedButton( - onPressed: () async { + ListTile( + title: Text("Drop Off Completed"), + subtitle: Text("Drop a pin at your location."), + onLongPress: () async { + //SessionData.currentDelivery!.MarkEndLocation(); + //SessionData.GetNewDelivery(); + + setState(() {}); + + SessionData.DirtyState = true; + SessionData.ActionPerformed(); + }, + onTap: () async { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), - title: Text("Are you sure you want to start a new delivery?"), + title: Text( + "Are you sure you want to mark a completed delivery?", + ), content: Text( - "Once ended, a marker for your current delivery will be dropped at your current location", + "A marker for your current delivery will be dropped at your current location", ), actions: [ ElevatedButton( onPressed: () { Navigator.pop(context); - SessionData.currentDelivery!.MarkEndLocation(); - SessionData.GetNewDelivery(); + SessionData.DropOffCompleted(); setState(() {}); @@ -291,7 +303,6 @@ class _HomePageState extends State { }, ); }, - child: Text("Start new delivery"), ), ], ); @@ -300,22 +311,41 @@ class _HomePageState extends State { Widget GetNonTripWidgets() { return Column( children: [ - ElevatedButton( - onPressed: () async { + ListTile( + title: Text("Start Active Time"), + subtitle: Text( + "Long press this when starting a trip, or when actively being paid for driving.", + ), + onLongPress: () async { + //Navigator.pop(context); + + SessionData.GetNewTrip(); + //SessionData.GetNewDelivery(); + + setState(() {}); + + SessionData.DirtyState = true; + SessionData.ActionPerformed(); + + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text("Active time started"))); + }, + onTap: () async { await showDialog( context: context, builder: (builder) { return AlertDialog( icon: Icon(Icons.warning), - title: Text("Are you sure you want to start a new trip?"), - content: Text("Starting a trip will also start a delivery."), + title: Text("Are you sure you want to start active time?"), + content: Text("Active paid time, trip, offer, etc."), actions: [ ElevatedButton( onPressed: () { Navigator.pop(context); SessionData.GetNewTrip(); - SessionData.GetNewDelivery(); + //SessionData.GetNewDelivery(); setState(() {}); @@ -335,19 +365,18 @@ class _HomePageState extends State { }, ); }, - child: Text("Start New Trip"), ), - ElevatedButton( - onPressed: () async { - if (SessionData.currentTrip != null || - SessionData.currentDelivery != null) { + SizedBox(height: 50), + ListTile( + onTap: () async { + if (SessionData.currentTrip != null) { showDialog( context: context, builder: (build) { return AlertDialog( title: Text("Cannot end work day"), content: Text( - "You must end the trip and any delivery before you can fully end the work day.", + "You must end your active time before you can fully end the work day.", ), ); }, @@ -407,7 +436,11 @@ class _HomePageState extends State { ); } }, - child: Text("End work day"), + title: Text("End work day"), + tileColor: LibACFlutterConstants.TITLEBAR_COLOR, + subtitle: Text( + "Ends the current work day, and marks the session as read only. Data will then be uploaded to the configured backend server.", + ), ), ], ); @@ -421,7 +454,7 @@ class _HomePageState extends State { style: TextStyle(fontSize: 18), ), if (SessionData.currentTrip != null) GetTripWidgets(), - if (SessionData.currentDelivery != null) GetDeliveryWidgets(), + if (SessionData.currentTrip != null) GetDeliveryWidgets(), if (SessionData.currentTrip == null) GetNonTripWidgets(), ], ); diff --git a/lib/pages/MapPage.dart b/lib/pages/MapPage.dart index 1c9b84e..fb25fdc 100644 --- a/lib/pages/MapPage.dart +++ b/lib/pages/MapPage.dart @@ -56,7 +56,22 @@ class _MapPage extends State { print("Total trips: ${SessionData.Trips.length}"); for (var trip in SessionData.Trips) { + for (var dropOff in trip.DropOffLocations) { + Markers.add( + Marker( + point: LatLng(dropOff.latitude, dropOff.longitude), + child: Stack( + children: GetDropOffWidgets( + dropOff, + trip.DropOffLocations.indexOf(dropOff) + 1, + SessionData.Trips.indexOf(trip) + 1, + ), + ), + ), + ); + } for (var dropOff in trip.deliveries) { + if (dropOff.endLocation == null) continue; Markers.add( Marker( point: LatLng( @@ -64,38 +79,63 @@ class _MapPage extends State { dropOff.endLocation!.longitude, ), child: Stack( - children: [ - IconButton( - onPressed: () { - showDialog( - context: context, - builder: (builder) { - return AlertDialog( - title: Text( - "Trip #${SessionData.Trips.indexOf(trip) + 1}; DropOff #${trip.deliveries.indexOf(dropOff) + 1}", - ), - ); - }, - ); - }, - icon: Icon( - Icons.location_on_rounded, - size: 24, - color: Colors.red, - ), - ), - ], + children: GetDropOffWidgets( + dropOff.endLocation!, + trip.deliveries.indexOf(dropOff) + 1, + SessionData.Trips.indexOf(trip) + 1, + ), ), ), ); print("Marker added"); } + + if (SessionData.IsOnTheClock) { + Markers.add( + Marker( + point: GetCurrentPosition(), + child: Stack( + children: [ + Icon(Icons.circle_outlined, color: Colors.lightBlue, size: 28), + Icon(Icons.circle, color: Colors.blue, size: 24), + ], + ), + ), + ); + } } setState(() {}); super.didChangeDependencies(); } + LatLng GetCurrentPosition() { + SmallPosition pos = SessionData.positions.last; + return LatLng(pos.latitude, pos.longitude); + } + + List GetDropOffWidgets( + SmallPosition pos, + int dropOffNumber, + int tripNumber, + ) { + return [ + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (builder) { + return AlertDialog( + title: Text("Trip #${tripNumber}; DropOff #${dropOffNumber}"), + ); + }, + ); + }, + icon: Icon(Icons.location_on_rounded, size: 24, color: Colors.red), + ), + ]; + } + @override void dispose() { SessionData.Calls.MapCallback = null; @@ -137,7 +177,10 @@ class _MapPage extends State { minZoom: 1, maxZoom: 30, initialZoom: 15, - initialCenter: initialPosition, + initialCenter: + SessionData.IsOnTheClock + ? GetCurrentPosition() + : initialPosition, keepAlive: false, ), children: [ diff --git a/lib/pages/WorkData.dart b/lib/pages/WorkData.dart index d2650a7..f7f2d7e 100644 --- a/lib/pages/WorkData.dart +++ b/lib/pages/WorkData.dart @@ -121,6 +121,15 @@ class _WorkData extends State { ElevatedButton( onPressed: () async { // Process data export to GPX format. + await showDialog( + context: context, + builder: (buildx) { + return AlertDialog( + title: Text("Not yet implemented"), + content: Text("GPX is not yet fully implemented."), + ); + }, + ); }, child: Text("Export as GPX"), ), diff --git a/pubspec.yaml b/pubspec.yaml index 67e4053..9085e1f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0-beta.34 +version: 1.0.0-beta.35 environment: sdk: ^3.7.2