From 583499ccd1ec9e742e841396dee49ee500471c12 Mon Sep 17 00:00:00 2001 From: stopflock Date: Wed, 1 Oct 2025 11:52:46 -0500 Subject: [PATCH] Tablet thing fixed - tweaking needed --- lib/screens/home_screen.dart | 5 +- lib/widgets/map_view.dart | 114 ++++++------------------------- lib/widgets/sheet_aware_map.dart | 49 +++++++++++++ 3 files changed, 73 insertions(+), 95 deletions(-) create mode 100644 lib/widgets/sheet_aware_map.dart diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index b3d9e9c..5c2d2aa 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -143,9 +143,8 @@ class _HomeScreenState extends State with TickerProviderStateMixin { _editSheetShown = false; } - // Calculate bottom padding for map (90% of active sheet height) + // Pass the active sheet height directly to the map final activeSheetHeight = _addSheetHeight > 0 ? _addSheetHeight : _editSheetHeight; - final mapBottomPadding = activeSheetHeight * 0.9; return MultiProvider( providers: [ @@ -190,7 +189,7 @@ class _HomeScreenState extends State with TickerProviderStateMixin { key: _mapViewKey, controller: _mapController, followMeMode: appState.followMeMode, - bottomPadding: mapBottomPadding, + sheetHeight: activeSheetHeight, onUserGesture: () { if (appState.followMeMode != FollowMeMode.off) { appState.setFollowMeMode(FollowMeMode.off); diff --git a/lib/widgets/map_view.dart b/lib/widgets/map_view.dart index b852a1e..27bde7b 100644 --- a/lib/widgets/map_view.dart +++ b/lib/widgets/map_view.dart @@ -25,6 +25,7 @@ import 'proximity_alert_banner.dart'; import '../dev_config.dart'; import '../app_state.dart' show FollowMeMode; import '../services/proximity_alert_service.dart'; +import 'sheet_aware_map.dart'; class MapView extends StatefulWidget { final AnimatedMapController controller; @@ -33,12 +34,12 @@ class MapView extends StatefulWidget { required this.controller, required this.followMeMode, required this.onUserGesture, - this.bottomPadding = 0.0, + this.sheetHeight = 0.0, }); final FollowMeMode followMeMode; final VoidCallback onUserGesture; - final double bottomPadding; + final double sheetHeight; @override State createState() => MapViewState(); @@ -185,53 +186,7 @@ class MapViewState extends State { super.dispose(); } - /// Calculate latitude offset to shift camera down (making content appear to move up) - /// when bottom sheet is open. Returns offset in degrees. - double _calculateCameraLatitudeOffset(double sheetHeight, double zoom) { - if (sheetHeight <= 0) return 0.0; - - // Convert sheet height to latitude degrees based on zoom level - // Rough approximation: 1 degree latitude ≈ 111,320 meters - final metersPerDegree = 111320.0; - final pixelsPerMeter = (256 * (1 << zoom.toInt())) / (2 * 3.14159 * 6378137); // Web Mercator - final metersOffset = sheetHeight * 0.4 / pixelsPerMeter; // 40% of sheet height - - return metersOffset / metersPerDegree; // Convert to degrees latitude - } - // Track last applied offset to detect changes - double _lastAppliedOffset = 0.0; - - /// Apply camera offset smoothly when bottom padding changes - void _applyCameraOffsetIfNeeded(double newOffset) { - if ((newOffset - _lastAppliedOffset).abs() < 0.00001) return; // No significant change - - try { - final currentCenter = _controller.mapController.camera.center; - final currentZoom = _controller.mapController.camera.zoom; - - // Calculate the difference in offset - final offsetDelta = newOffset - _lastAppliedOffset; - - // Apply the offset delta (move camera down to make content appear to move up) - final newCenter = LatLng( - currentCenter.latitude - offsetDelta, // Subtract to move camera down - currentCenter.longitude, - ); - - // Animate the camera movement smoothly - _controller.animateTo( - dest: newCenter, - zoom: currentZoom, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, - ); - - _lastAppliedOffset = newOffset; - } catch (_) { - // Controller not ready yet - } - } void _onCamerasUpdated() { if (mounted) setState(() {}); @@ -309,24 +264,9 @@ class MapViewState extends State { controller: _controller, ); } - - // Handle bottom padding changes (sheet opening/closing) - if (widget.bottomPadding != oldWidget.bottomPadding) { - final currentZoom = _safeZoom(); - final newOffset = _calculateCameraLatitudeOffset(widget.bottomPadding, currentZoom); - WidgetsBinding.instance.addPostFrameCallback((_) { - _applyCameraOffsetIfNeeded(newOffset); - }); - } } - double _safeZoom() { - try { - return _controller.mapController.camera.zoom; - } catch (_) { - return 15.0; - } - } + @@ -358,19 +298,12 @@ class MapViewState extends State { }); } - final zoom = _safeZoom(); - - // Calculate camera offset based on bottom padding (sheet height) - final latitudeOffset = _calculateCameraLatitudeOffset(widget.bottomPadding, zoom); - // Seed add‑mode target once, after first controller center is available. if (session != null && session.target == null) { try { final center = _controller.mapController.camera.center; - // Apply offset compensation when storing the target (so pin appears in visible area) - final adjustedCenter = LatLng(center.latitude + latitudeOffset, center.longitude); WidgetsBinding.instance.addPostFrameCallback( - (_) => appState.updateSession(target: adjustedCenter), + (_) => appState.updateSession(target: center), ); } catch (_) {/* controller not ready yet */} } @@ -380,9 +313,7 @@ class MapViewState extends State { WidgetsBinding.instance.addPostFrameCallback( (_) { try { - // Apply offset when moving to edit target (shift camera down so target is in visible area) - final adjustedTarget = LatLng(editSession.target.latitude - latitudeOffset, editSession.target.longitude); - _controller.mapController.move(adjustedTarget, _controller.mapController.camera.zoom); + _controller.mapController.move(editSession.target, _controller.mapController.camera.zoom); } catch (_) {/* controller not ready yet */} }, ); @@ -407,9 +338,17 @@ class MapViewState extends State { userLocation: _gpsController.currentLocation, ); + // Get current zoom level for direction cones + double currentZoom = 15.0; // fallback + try { + currentZoom = _controller.mapController.camera.zoom; + } catch (_) { + // Controller not ready yet, use fallback + } + final overlays = DirectionConesBuilder.buildDirectionCones( cameras: cameras, - zoom: zoom, + zoom: currentZoom, session: session, editSession: editSession, ); @@ -422,14 +361,9 @@ class MapViewState extends State { if (session != null || editSession != null) { try { final center = _controller.mapController.camera.center; - // Show the pin in the visually centered position (accounting for sheet offset) - final adjustedCenter = LatLng( - center.latitude + latitudeOffset, - center.longitude, - ); centerMarkers.add( Marker( - point: adjustedCenter, + point: center, width: kCameraIconDiameter, height: kCameraIconDiameter, child: CameraIcon( @@ -454,7 +388,9 @@ class MapViewState extends State { return Stack( children: [ - FlutterMap( + SheetAwareMap( + sheetHeight: widget.sheetHeight, + child: FlutterMap( key: ValueKey('map_${appState.offlineMode}_${appState.selectedTileType?.id ?? 'none'}_${_tileManager.mapRebuildKey}'), mapController: _controller.mapController, options: MapOptions( @@ -465,18 +401,11 @@ class MapViewState extends State { setState(() {}); // Instant UI update for zoom, etc. if (gesture) widget.onUserGesture(); - // Calculate current offset compensation for session targets - final currentLatOffset = _calculateCameraLatitudeOffset(widget.bottomPadding, pos.zoom); - if (session != null) { - // Store the target with offset compensation (so pin appears in visible area above sheet) - final adjustedTarget = LatLng(pos.center.latitude + currentLatOffset, pos.center.longitude); - appState.updateSession(target: adjustedTarget); + appState.updateSession(target: pos.center); } if (editSession != null) { - // Store the target with offset compensation - final adjustedTarget = LatLng(pos.center.latitude + currentLatOffset, pos.center.longitude); - appState.updateEditSession(target: adjustedTarget); + appState.updateEditSession(target: pos.center); } // Start dual-source waiting when map moves (user is expecting new tiles AND nodes) @@ -532,6 +461,7 @@ class MapViewState extends State { ), ], ), + ), // All map overlays (mode indicator, zoom, attribution, add pin) MapOverlays( diff --git a/lib/widgets/sheet_aware_map.dart b/lib/widgets/sheet_aware_map.dart new file mode 100644 index 0000000..17f2613 --- /dev/null +++ b/lib/widgets/sheet_aware_map.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +/// A wrapper that shifts a map's visual positioning to account for bottom sheets. +/// +/// When a sheet is open, moves the map upward by the sheet height while extending +/// the map rendering area to fill the screen. This keeps the bottom edge visible +/// while shifting the visual center up so pins appear above the sheet. +class SheetAwareMap extends StatelessWidget { + const SheetAwareMap({ + super.key, + required this.child, + this.sheetHeight = 0.0, + this.animationDuration = const Duration(milliseconds: 300), + }); + + /// The map widget to position + final Widget child; + + /// Current height of the bottom sheet + final double sheetHeight; + + /// Duration for smooth transitions when sheet height changes + final Duration animationDuration; + + @override + Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; + + return LayoutBuilder( + builder: (context, constraints) { + return Stack( + children: [ + AnimatedPositioned( + duration: animationDuration, + curve: Curves.easeOut, + // Move the map up by the sheet height + top: -sheetHeight, + left: 0, + right: 0, + // Extend the height to compensate and fill screen + height: screenHeight + sheetHeight, + child: child, + ), + ], + ); + }, + ); + } +} \ No newline at end of file