Refactoring QOL Changes

This commit is contained in:
zontreck 2025-07-22 12:17:11 -07:00
parent 7e13057e43
commit 845e35fe74
6 changed files with 176 additions and 80 deletions

View file

@ -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;

View file

@ -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<Trip> Trips = [];
static Delivery? currentDelivery;
//static Delivery? currentDelivery;
static Trip? currentTrip;
static List<SmallPosition> positions = [];
static late StreamSubscription<Position> _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<void> 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<void> 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<Delivery> deliveries = [];
List<SmallPosition> 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<String, dynamic> toJsonMap() {
Map<String, Object> 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();
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);
}
return ct;
}
@ -864,12 +868,19 @@ class Trip {
trip.EndTime = DateTime.parse(tag.get("end")!.asString());
}
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;
}
}

View file

@ -223,7 +223,7 @@ class _HomePageState extends State<HomePage> {
onPressed: () {
Navigator.pop(context);
SessionData.currentDelivery!.MarkEndLocation();
//SessionData.currentDelivery!.MarkEndLocation();
SessionData.EndTrip();
@ -254,24 +254,36 @@ class _HomePageState extends State<HomePage> {
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<HomePage> {
},
);
},
child: Text("Start new delivery"),
),
],
);
@ -300,22 +311,41 @@ class _HomePageState extends State<HomePage> {
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<HomePage> {
},
);
},
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<HomePage> {
);
}
},
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<HomePage> {
style: TextStyle(fontSize: 18),
),
if (SessionData.currentTrip != null) GetTripWidgets(),
if (SessionData.currentDelivery != null) GetDeliveryWidgets(),
if (SessionData.currentTrip != null) GetDeliveryWidgets(),
if (SessionData.currentTrip == null) GetNonTripWidgets(),
],
);

View file

@ -56,44 +56,84 @@ class _MapPage extends State<MapPage> {
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(
dropOff.endLocation!.latitude,
dropOff.endLocation!.longitude,
),
child: Stack(
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<Widget> GetDropOffWidgets(
SmallPosition pos,
int dropOffNumber,
int tripNumber,
) {
return [
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (builder) {
return AlertDialog(
title: Text(
"Trip #${SessionData.Trips.indexOf(trip) + 1}; DropOff #${trip.deliveries.indexOf(dropOff) + 1}",
),
title: Text("Trip #${tripNumber}; DropOff #${dropOffNumber}"),
);
},
);
},
icon: Icon(
Icons.location_on_rounded,
size: 24,
color: Colors.red,
icon: Icon(Icons.location_on_rounded, size: 24, color: Colors.red),
),
),
],
),
),
);
print("Marker added");
}
}
setState(() {});
super.didChangeDependencies();
];
}
@override
@ -137,7 +177,10 @@ class _MapPage extends State<MapPage> {
minZoom: 1,
maxZoom: 30,
initialZoom: 15,
initialCenter: initialPosition,
initialCenter:
SessionData.IsOnTheClock
? GetCurrentPosition()
: initialPosition,
keepAlive: false,
),
children: [

View file

@ -121,6 +121,15 @@ class _WorkData extends State<WorkDataPage> {
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"),
),

View file

@ -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