mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-05-14 21:28:08 +02:00
Proper centering for all node sheets. still jumps between tags and edit.
This commit is contained in:
@@ -11,9 +11,11 @@ import '../services/localization_service.dart';
|
||||
|
||||
import '../widgets/add_node_sheet.dart';
|
||||
import '../widgets/edit_node_sheet.dart';
|
||||
import '../widgets/node_tag_sheet.dart';
|
||||
import '../widgets/camera_provider_with_cache.dart';
|
||||
import '../widgets/download_area_dialog.dart';
|
||||
import '../widgets/measured_sheet.dart';
|
||||
import '../models/osm_node.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
@@ -28,9 +30,10 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
late final AnimatedMapController _mapController;
|
||||
bool _editSheetShown = false;
|
||||
|
||||
// Track sheet heights for map padding
|
||||
// Track sheet heights for map positioning
|
||||
double _addSheetHeight = 0.0;
|
||||
double _editSheetHeight = 0.0;
|
||||
double _tagSheetHeight = 0.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -110,6 +113,11 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
// Disable follow-me when editing a camera so the map doesn't jump around
|
||||
appState.setFollowMeMode(FollowMeMode.off);
|
||||
|
||||
// Close any existing tag sheet first
|
||||
if (_tagSheetHeight > 0) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
final session = appState.editSession!; // should be non-null when this is called
|
||||
|
||||
final controller = _scaffoldKey.currentState!.showBottomSheet(
|
||||
@@ -131,6 +139,26 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
});
|
||||
}
|
||||
|
||||
void openNodeTagSheet(OsmNode node) {
|
||||
final controller = _scaffoldKey.currentState!.showBottomSheet(
|
||||
(ctx) => MeasuredSheet(
|
||||
onHeightChanged: (height) {
|
||||
setState(() {
|
||||
_tagSheetHeight = height;
|
||||
});
|
||||
},
|
||||
child: NodeTagSheet(node: node),
|
||||
),
|
||||
);
|
||||
|
||||
// Reset height when sheet is dismissed
|
||||
controller.closed.then((_) {
|
||||
setState(() {
|
||||
_tagSheetHeight = 0.0;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appState = context.watch<AppState>();
|
||||
@@ -144,7 +172,9 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
}
|
||||
|
||||
// Pass the active sheet height directly to the map
|
||||
final activeSheetHeight = _addSheetHeight > 0 ? _addSheetHeight : _editSheetHeight;
|
||||
final activeSheetHeight = _addSheetHeight > 0
|
||||
? _addSheetHeight
|
||||
: (_editSheetHeight > 0 ? _editSheetHeight : _tagSheetHeight);
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
@@ -190,6 +220,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
controller: _mapController,
|
||||
followMeMode: appState.followMeMode,
|
||||
sheetHeight: activeSheetHeight,
|
||||
onNodeTap: openNodeTagSheet,
|
||||
onUserGesture: () {
|
||||
if (appState.followMeMode != FollowMeMode.off) {
|
||||
appState.setFollowMeMode(FollowMeMode.off);
|
||||
|
||||
@@ -12,7 +12,14 @@ import '../camera_icon.dart';
|
||||
class CameraMapMarker extends StatefulWidget {
|
||||
final OsmNode node;
|
||||
final MapController mapController;
|
||||
const CameraMapMarker({required this.node, required this.mapController, Key? key}) : super(key: key);
|
||||
final void Function(OsmNode)? onNodeTap;
|
||||
|
||||
const CameraMapMarker({
|
||||
required this.node,
|
||||
required this.mapController,
|
||||
this.onNodeTap,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CameraMapMarker> createState() => _CameraMapMarkerState();
|
||||
@@ -25,11 +32,20 @@ class _CameraMapMarkerState extends State<CameraMapMarker> {
|
||||
|
||||
void _onTap() {
|
||||
_tapTimer = Timer(tapTimeout, () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (_) => NodeTagSheet(node: widget.node),
|
||||
showDragHandle: true,
|
||||
);
|
||||
// Center on the node when opening the tag sheet
|
||||
// This prevents jumping when transitioning to edit mode
|
||||
widget.mapController.move(widget.node.coord, widget.mapController.camera.zoom);
|
||||
|
||||
// Use callback if provided, otherwise fallback to direct modal
|
||||
if (widget.onNodeTap != null) {
|
||||
widget.onNodeTap!(widget.node);
|
||||
} else {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (_) => NodeTagSheet(node: widget.node),
|
||||
showDragHandle: true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,6 +95,7 @@ class CameraMarkersBuilder {
|
||||
required List<OsmNode> cameras,
|
||||
required MapController mapController,
|
||||
LatLng? userLocation,
|
||||
void Function(OsmNode)? onNodeTap,
|
||||
}) {
|
||||
final markers = <Marker>[
|
||||
// Camera markers
|
||||
@@ -88,7 +105,11 @@ class CameraMarkersBuilder {
|
||||
point: n.coord,
|
||||
width: kCameraIconDiameter,
|
||||
height: kCameraIconDiameter,
|
||||
child: CameraMapMarker(node: n, mapController: mapController),
|
||||
child: CameraMapMarker(
|
||||
node: n,
|
||||
mapController: mapController,
|
||||
onNodeTap: onNodeTap,
|
||||
),
|
||||
)),
|
||||
|
||||
// User location marker
|
||||
|
||||
@@ -35,11 +35,13 @@ class MapView extends StatefulWidget {
|
||||
required this.followMeMode,
|
||||
required this.onUserGesture,
|
||||
this.sheetHeight = 0.0,
|
||||
this.onNodeTap,
|
||||
});
|
||||
|
||||
final FollowMeMode followMeMode;
|
||||
final VoidCallback onUserGesture;
|
||||
final double sheetHeight;
|
||||
final void Function(OsmNode)? onNodeTap;
|
||||
|
||||
@override
|
||||
State<MapView> createState() => MapViewState();
|
||||
@@ -308,16 +310,8 @@ class MapViewState extends State<MapView> {
|
||||
} catch (_) {/* controller not ready yet */}
|
||||
}
|
||||
|
||||
// For edit sessions, center the map on the camera being edited initially
|
||||
if (editSession != null && _controller.mapController.camera.center != editSession.target) {
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) {
|
||||
try {
|
||||
_controller.mapController.move(editSession.target, _controller.mapController.camera.zoom);
|
||||
} catch (_) {/* controller not ready yet */}
|
||||
},
|
||||
);
|
||||
}
|
||||
// Edit sessions don't need to center - we're already centered from the node tap
|
||||
// SheetAwareMap handles the visual positioning
|
||||
|
||||
// Fetch cached cameras for current map bounds (using Consumer so overlays redraw instantly)
|
||||
Widget cameraLayers = Consumer<CameraProviderWithCache>(
|
||||
@@ -336,6 +330,7 @@ class MapViewState extends State<MapView> {
|
||||
cameras: cameras,
|
||||
mapController: _controller.mapController,
|
||||
userLocation: _gpsController.currentLocation,
|
||||
onNodeTap: widget.onNodeTap,
|
||||
);
|
||||
|
||||
// Get current zoom level for direction cones
|
||||
|
||||
Reference in New Issue
Block a user