Tablet thing fixed - tweaking needed

This commit is contained in:
stopflock
2025-10-01 11:52:46 -05:00
parent 7ff9273f47
commit 583499ccd1
3 changed files with 73 additions and 95 deletions

View File

@@ -143,9 +143,8 @@ class _HomeScreenState extends State<HomeScreen> 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<HomeScreen> with TickerProviderStateMixin {
key: _mapViewKey,
controller: _mapController,
followMeMode: appState.followMeMode,
bottomPadding: mapBottomPadding,
sheetHeight: activeSheetHeight,
onUserGesture: () {
if (appState.followMeMode != FollowMeMode.off) {
appState.setFollowMeMode(FollowMeMode.off);

View File

@@ -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<MapView> createState() => MapViewState();
@@ -185,53 +186,7 @@ class MapViewState extends State<MapView> {
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<MapView> {
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<MapView> {
});
}
final zoom = _safeZoom();
// Calculate camera offset based on bottom padding (sheet height)
final latitudeOffset = _calculateCameraLatitudeOffset(widget.bottomPadding, zoom);
// Seed addmode 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<MapView> {
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<MapView> {
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<MapView> {
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<MapView> {
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<MapView> {
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<MapView> {
),
],
),
),
// All map overlays (mode indicator, zoom, attribution, add pin)
MapOverlays(

View File

@@ -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,
),
],
);
},
);
}
}