// lib/dev_config.dart import 'package:flutter/material.dart'; /// Developer/build-time configuration for global/non-user-tunable constants. // Fallback tile storage estimate (KB per tile), used when no preview tile data is available const double kFallbackTileEstimateKb = 25.0; // Preview tile coordinates for tile provider previews and size estimates const int kPreviewTileZoom = 18; const int kPreviewTileY = 101300; const int kPreviewTileX = 41904; // Direction cone for map view const double kDirectionConeHalfAngle = 35.0; // degrees const double kDirectionConeBaseLength = 5; // multiplier const Color kDirectionConeColor = Color(0xD0767474); // FOV cone color const double kDirectionConeOpacity = 0.5; // Fill opacity for FOV cones // Base values for thickness - use helper functions below for pixel-ratio scaling const double _kDirectionConeBorderWidthBase = 1.6; // Bottom button bar positioning const double kBottomButtonBarOffset = 4.0; // Distance from screen bottom (above safe area) const double kButtonBarHeight = 60.0; // Button height (48) + padding (12) // Map overlay spacing relative to button bar top const double kAttributionSpacingAboveButtonBar = 10.0; // Attribution above button bar top const double kZoomIndicatorSpacingAboveButtonBar = 40.0; // Zoom indicator above button bar top const double kScaleBarSpacingAboveButtonBar = 70.0; // Scale bar above button bar top const double kZoomControlsSpacingAboveButtonBar = 20.0; // Zoom controls above button bar top // Helper to calculate bottom position relative to button bar double bottomPositionFromButtonBar(double spacingAboveButtonBar, double safeAreaBottom) { return safeAreaBottom + kBottomButtonBarOffset + kButtonBarHeight + spacingAboveButtonBar; } // Helper to get left positioning that accounts for safe area (for landscape mode) double leftPositionWithSafeArea(double baseLeft, EdgeInsets safeArea) { return baseLeft + safeArea.left; } // Helper to get right positioning that accounts for safe area (for landscape mode) double rightPositionWithSafeArea(double baseRight, EdgeInsets safeArea) { return baseRight + safeArea.right; } // Helper to get top positioning that accounts for safe area double topPositionWithSafeArea(double baseTop, EdgeInsets safeArea) { return baseTop + safeArea.top; } // Client name for OSM uploads ("created_by" tag) const String kClientName = 'DeFlock'; // Note: Version is now dynamically retrieved from VersionService // Upload and changeset configuration const Duration kUploadHttpTimeout = Duration(seconds: 30); // HTTP request timeout for uploads const Duration kUploadQueueProcessingInterval = Duration(seconds: 5); // How often to check for new uploads to start const int kMaxConcurrentUploads = 5; // Maximum number of uploads processing simultaneously const Duration kChangesetCloseInitialRetryDelay = Duration(seconds: 10); const Duration kChangesetCloseMaxRetryDelay = Duration(minutes: 5); // Cap at 5 minutes const Duration kChangesetAutoCloseTimeout = Duration(minutes: 59); // Give up and trust OSM auto-close const double kChangesetCloseBackoffMultiplier = 2.0; // Navigation routing configuration const Duration kNavigationRoutingTimeout = Duration(seconds: 90); // HTTP timeout for routing requests // Overpass API configuration const Duration kOverpassQueryTimeout = Duration(seconds: 45); // Timeout for Overpass API queries (was 25s hardcoded) // Suspected locations CSV URL const String kSuspectedLocationsCsvUrl = 'https://alprwatch.org/suspected-locations/deflock-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 // Navigation features - set to false to hide navigation UI elements while in development const bool kEnableNavigationFeatures = true; // Hide navigation until fully implemented // Node editing features - set to false to temporarily disable editing const bool kEnableNodeEdits = true; // Set to false to temporarily disable node editing // Node extraction features - set to false to hide extract functionality for constrained nodes const bool kEnableNodeExtraction = false; // Set to true to enable extract from way/relation feature (WIP) /// Navigation availability: only dev builds, and only when online bool enableNavigationFeatures({required bool offlineMode}) { return kEnableNavigationFeatures && !offlineMode; } // Marker/node interaction const int kNodeMinZoomLevel = 10; // Minimum zoom to show nodes (Overpass) const int kOsmApiMinZoomLevel = 13; // Minimum zoom for OSM API bbox queries (sandbox mode) const int kMinZoomForNodeEditingSheets = 15; // Minimum zoom to open add/edit node sheets const int kMinZoomForOfflineDownload = 10; // Minimum zoom to download offline areas (prevents large area crashes) const Duration kMarkerTapTimeout = Duration(milliseconds: 250); const Duration kDebounceCameraRefresh = Duration(milliseconds: 500); // Pre-fetch area configuration const double kPreFetchAreaExpansionMultiplier = 3.0; // Expand visible bounds by this factor for pre-fetching const double kNodeRenderingBoundsExpansion = 1.3; // Expand visible bounds by this factor for node rendering to prevent edge blinking const double kRouteProximityThresholdMeters = 500.0; // Distance threshold for determining if user is near route when resuming navigation const double kResumeNavigationZoomLevel = 16.0; // Zoom level when resuming navigation const int kPreFetchZoomLevel = 10; // Always pre-fetch at this zoom level for consistent area sizes const int kMaxPreFetchSplitDepth = 3; // Maximum recursive splits when hitting Overpass node limit // Data refresh configuration const int kDataRefreshIntervalSeconds = 60; // Refresh cached data after this many seconds // Follow-me mode smooth transitions const Duration kFollowMeAnimationDuration = Duration(milliseconds: 600); const double kMinSpeedForRotationMps = 1.0; // Minimum speed (m/s) to apply rotation // Sheet content configuration const double kMaxTagListHeightRatioPortrait = 0.3; // Maximum height for tag lists in portrait mode const double kMaxTagListHeightRatioLandscape = 0.2; // Maximum height for tag lists in landscape mode /// Get appropriate tag list height ratio based on screen orientation double getTagListHeightRatio(BuildContext context) { final size = MediaQuery.of(context).size; final isLandscape = size.width > size.height; return isLandscape ? kMaxTagListHeightRatioLandscape : kMaxTagListHeightRatioPortrait; } // Proximity alerts configuration const int kProximityAlertDefaultDistance = 400; // meters const int kProximityAlertMinDistance = 50; // meters const int kProximityAlertMaxDistance = 1600; // meters const Duration kProximityAlertCooldown = Duration(minutes: 10); // Cooldown between alerts for same node // Node proximity warning configuration (for new/edited nodes that are too close to existing ones) const double kNodeProximityWarningDistance = 15.0; // meters - distance threshold to show warning // Positioning tutorial configuration const double kPositioningTutorialBlurSigma = 3.0; // Blur strength for sheet overlay const double kPositioningTutorialMinMovementMeters = 1.0; // Minimum map movement to complete tutorial // Navigation route planning configuration const double kNavigationMinRouteDistance = 100.0; // meters - minimum distance between start and end points const double kNavigationDistanceWarningThreshold = 20000.0; // meters - distance threshold for timeout warning (30km) // Node display configuration const int kDefaultMaxNodes = 500; // Default maximum number of nodes to render on the map at once // NSI (Name Suggestion Index) configuration const int kNSIMinimumHitCount = 500; // Minimum hit count for NSI suggestions to be considered useful const int kNSIMaxSuggestions = 10; // Maximum number of tag value suggestions to fetch and display // Map interaction configuration const double kNodeDoubleTapZoomDelta = 1.0; // How much to zoom in when double-tapping nodes (was 1.0) const double kScrollWheelVelocity = 0.01; // Mouse scroll wheel zoom speed (default 0.005) const double kPinchZoomThreshold = 0.2; // How much pinch required to start zoom (reduced for gesture race) const double kPinchMoveThreshold = 30.0; // How much drag required for two-finger pan (default 40.0) const double kRotationThreshold = 6.0; // Degrees of rotation required before map actually rotates (Google Maps style) // Tile fetch configuration (brutalist approach: simple, configurable, unlimited retries) const int kTileFetchConcurrentThreads = 8; // Reduced from 10 to 8 for better cross-platform performance const int kTileFetchInitialDelayMs = 150; // Reduced from 200ms for faster retries const double kTileFetchBackoffMultiplier = 1.4; // Slightly reduced for faster recovery const int kTileFetchMaxDelayMs = 4000; // Reduced from 5000ms for faster max retry const int kTileFetchRandomJitterMs = 50; // Reduced jitter for more predictable timing const int kTileFetchMaxQueueSize = 100; // Reasonable queue size to prevent memory bloat // Note: Removed max attempts - tiles retry indefinitely until they succeed or are canceled // User download max zoom span (user can download up to kMaxUserDownloadZoomSpan zooms above min) const int kMaxUserDownloadZoomSpan = 7; // Download area limits and constants const int kMaxReasonableTileCount = 20000; const int kAbsoluteMaxTileCount = 50000; const int kAbsoluteMaxZoom = 23; // Node icon configuration const double kNodeIconDiameter = 18.0; const double _kNodeRingThicknessBase = 2.5; const double kNodeDotOpacity = 0.3; // Opacity for the grey dot interior const Color kNodeRingColorReal = Color(0xFF3036F0); // Real nodes from OSM - blue const Color kNodeRingColorMock = Color(0xD0FFFFFF); // Add node mock point - white const Color kNodeRingColorPending = Color(0xD09C27B0); // Submitted/pending nodes - purple const Color kNodeRingColorEditing = Color(0xD0FF9800); // Node being edited - orange const Color kNodeRingColorPendingEdit = Color(0xD0757575); // Original node with pending edit - grey const Color kNodeRingColorPendingDeletion = Color(0xC0F44336); // Node pending deletion - red, slightly transparent // Direction slider control buttons configuration const double kDirectionButtonMinWidth = 22.0; const double kDirectionButtonMinHeight = 32.0; // Helper functions for pixel-ratio scaling double getDirectionConeBorderWidth(BuildContext context) { // return _kDirectionConeBorderWidthBase * MediaQuery.of(context).devicePixelRatio; return _kDirectionConeBorderWidthBase; } double getNodeRingThickness(BuildContext context) { // return _kNodeRingThicknessBase * MediaQuery.of(context).devicePixelRatio; return _kNodeRingThicknessBase; }