From d04064d17a15a1191237e35b9725c1239f43ec90 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 6 Mar 2026 09:08:28 +0100 Subject: [PATCH] refactor: make compass button dynamic - only show when map is rotated - Convert CompassMapPluginWidget from StatelessWidget to StatefulWidget - Add periodic rotation monitoring (every 100ms) to detect map rotation changes - Button only appears when rotation != 0 (map is rotated away from north) - Button automatically disappears when map is reset to north (rotation = 0) - Improves UX by reducing visual clutter when map is already north-aligned - Add tooltip 'Go to North' for better user guidance - Gracefully handle errors and only update state when widget is mounted --- lib/compassMapPlugin.dart | 105 ++++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 20 deletions(-) diff --git a/lib/compassMapPlugin.dart b/lib/compassMapPlugin.dart index 922ec45..18434f0 100644 --- a/lib/compassMapPlugin.dart +++ b/lib/compassMapPlugin.dart @@ -1,28 +1,90 @@ +import 'dart:async'; + import 'package:comunes_flutter/comunes_flutter.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; /// Compass button widget for resetting map rotation to north -class CompassMapPluginWidget extends StatelessWidget { +/// Only visible when map is rotated (rotation != 0) +class CompassMapPluginWidget extends StatefulWidget { + @override + _CompassMapPluginWidgetState createState() => _CompassMapPluginWidgetState(); +} + +class _CompassMapPluginWidgetState extends State { + late MapController _mapController; + bool _isRotated = false; + late Timer _rotationCheckTimer; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + try { + _mapController = MapController.of(context); + _initRotationMonitoring(); + } catch (e) { + print('Error getting map controller: $e'); + } + } + + void _initRotationMonitoring() { + // Check rotation periodically (every 100ms) to detect changes + _rotationCheckTimer = Timer.periodic(Duration(milliseconds: 100), (_) { + _checkRotation(); + }); + + // Initial state check + _checkRotation(); + } + + void _checkRotation() { + try { + if (!mounted) return; + + final rotation = _mapController.camera.rotation; + final isRotated = rotation.abs() > 0.0; + + if (isRotated != _isRotated) { + setState(() { + _isRotated = isRotated; + }); + } + } catch (e) { + // Silently ignore errors (controller may not be ready) + } + } + + void _resetRotation() { + try { + final controller = MapController.of(context); + controller.rotate(0); + } catch (e) { + print('Error resetting rotation: $e'); + } + } + @override Widget build(BuildContext context) { return LayoutBuilder( - builder: (context, constraints) => - Stack(fit: StackFit.expand, children: [ - Positioned( - top: 10.0, - right: 10.0, - child: new CenteredRow( - children: [ - new Column( + builder: (context, constraints) => Stack( + fit: StackFit.expand, + children: [ + if (_isRotated) + Positioned( + top: 10.0, + right: 10.0, + child: CenteredRow( children: [ - _compassButton(context), + Column( + children: [ + _compassButton(context), + ], + ) ], - ) - ], - ), - ) - ])); + ), + ) + ], + )); } FloatingActionButton _compassButton(BuildContext context) { @@ -30,12 +92,15 @@ class CompassMapPluginWidget extends StatelessWidget { backgroundColor: Colors.black26, mini: true, heroTag: 'compass_button', - onPressed: () { - final controller = MapController.of(context); - // Reset rotation to 0 (north) while keeping center and zoom - controller.rotate(0); - }, + tooltip: 'Go to North', + onPressed: _resetRotation, child: Icon(Icons.explore), ); } + + @override + void dispose() { + _rotationCheckTimer.cancel(); + super.dispose(); + } }