mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-02-12 16:52:51 +00:00
Tablet thing fixed - tweaking needed
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 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<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(
|
||||
|
||||
49
lib/widgets/sheet_aware_map.dart
Normal file
49
lib/widgets/sheet_aware_map.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user