From b80e1094af65d63371be665ad498a977923c88cb Mon Sep 17 00:00:00 2001 From: stopflock Date: Fri, 24 Oct 2025 18:28:39 -0500 Subject: [PATCH] deletions no longer using stub profile, more handling of builtin profiles by lists. --- lib/dev_config.dart | 2 +- lib/models/pending_upload.dart | 21 +++++++++++++++------ lib/services/uploader.dart | 10 +++++++++- lib/state/upload_queue_state.dart | 4 ++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/dev_config.dart b/lib/dev_config.dart index 2d57bfc..e5dc173 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -44,7 +44,7 @@ const String kClientName = 'DeFlock'; const String kSuspectedLocationsCsvUrl = 'https://alprwatch.org/pub/flock_utilities_mini_latest.csv'; // Development/testing features - set to false for production builds -const bool kEnableDevelopmentModes = false; // Set to false to hide sandbox/simulate modes and force production mode +const bool kEnableDevelopmentModes = true; // Set to false to hide sandbox/simulate modes and force production mode // Navigation features - set to false to hide navigation UI elements while in development const bool kEnableNavigationFeatures = kEnableDevelopmentModes; // Hide navigation until fully implemented diff --git a/lib/models/pending_upload.dart b/lib/models/pending_upload.dart index e99be93..6c0aea0 100644 --- a/lib/models/pending_upload.dart +++ b/lib/models/pending_upload.dart @@ -8,7 +8,7 @@ enum UploadOperation { create, modify, delete } class PendingUpload { final LatLng coord; final double direction; - final NodeProfile profile; + final NodeProfile? profile; final OperatorProfile? operatorProfile; final UploadMode uploadMode; // Capture upload destination when queued final UploadOperation operation; // Type of operation: create, modify, or delete @@ -21,7 +21,7 @@ class PendingUpload { PendingUpload({ required this.coord, required this.direction, - required this.profile, + this.profile, this.operatorProfile, required this.uploadMode, required this.operation, @@ -34,6 +34,10 @@ class PendingUpload { (operation == UploadOperation.create && originalNodeId == null) || (operation != UploadOperation.create && originalNodeId != null), 'originalNodeId must be null for create operations and non-null for modify/delete operations' + ), + assert( + (operation == UploadOperation.delete) || (profile != null), + 'profile is required for create and modify operations' ); // True if this is an edit of an existing node, false if it's a new node @@ -56,7 +60,12 @@ class PendingUpload { // Get combined tags from node profile and operator profile Map getCombinedTags() { - final tags = Map.from(profile.tags); + // Deletions don't need tags + if (operation == UploadOperation.delete || profile == null) { + return {}; + } + + final tags = Map.from(profile!.tags); // Add operator profile tags (they override node profile tags if there are conflicts) if (operatorProfile != null) { @@ -64,7 +73,7 @@ class PendingUpload { } // Add direction if required - if (profile.requiresDirection) { + if (profile!.requiresDirection) { tags['direction'] = direction.toStringAsFixed(0); } @@ -75,7 +84,7 @@ class PendingUpload { 'lat': coord.latitude, 'lon': coord.longitude, 'dir': direction, - 'profile': profile.toJson(), + 'profile': profile?.toJson(), 'operatorProfile': operatorProfile?.toJson(), 'uploadMode': uploadMode.index, 'operation': operation.index, @@ -91,7 +100,7 @@ class PendingUpload { direction: j['dir'], profile: j['profile'] is Map ? NodeProfile.fromJson(j['profile']) - : throw Exception('PendingUpload missing required profile data - this should never happen'), + : null, // Profile is optional for deletions operatorProfile: j['operatorProfile'] != null ? OperatorProfile.fromJson(j['operatorProfile']) : null, diff --git a/lib/services/uploader.dart b/lib/services/uploader.dart index 2b6c4e5..797a60a 100644 --- a/lib/services/uploader.dart +++ b/lib/services/uploader.dart @@ -17,6 +17,12 @@ class Uploader { try { print('Uploader: Starting upload for node at ${p.coord.latitude}, ${p.coord.longitude}'); + // Safety check: create and modify operations MUST have profiles + if ((p.operation == UploadOperation.create || p.operation == UploadOperation.modify) && p.profile == null) { + print('Uploader: ERROR - ${p.operation.name} operation attempted without profile data'); + return false; + } + // 1. open changeset String action; switch (p.operation) { @@ -30,11 +36,13 @@ class Uploader { action = 'Delete'; break; } + // Generate appropriate comment based on operation type + final profileName = p.profile?.name ?? 'surveillance'; final csXml = ''' - + '''; print('Uploader: Creating changeset...'); diff --git a/lib/state/upload_queue_state.dart b/lib/state/upload_queue_state.dart index 32f1aed..c227cff 100644 --- a/lib/state/upload_queue_state.dart +++ b/lib/state/upload_queue_state.dart @@ -109,8 +109,8 @@ class UploadQueueState extends ChangeNotifier { void addFromNodeDeletion(OsmNode node, {required UploadMode uploadMode}) { final upload = PendingUpload( coord: node.coord, - direction: node.directionDeg ?? 0, // Use existing direction or default to 0 - profile: NodeProfile.genericAlpr(), // Dummy profile - not used for deletions + direction: node.directionDeg ?? 0, // Direction not used for deletions but required for API + profile: null, // No profile needed for deletions - just delete by node ID uploadMode: uploadMode, operation: UploadOperation.delete, originalNodeId: node.id,