feat: Add zoom level clamping for WMS layer switching and improve message filtering in simple mode

This commit is contained in:
Janez T
2025-10-27 22:28:46 +01:00
parent b4bbaf3109
commit f707e2233b
23 changed files with 212 additions and 20 deletions

View File

@@ -1683,6 +1683,16 @@
"description": "Beschreibung für Karte-drehen-Umschalter"
},
"resetMapRotation": "Drehung zurücksetzen",
"@resetMapRotation": {
"description": "Schaltfläche zum Zurücksetzen der Kartendrehung nach Norden"
},
"resetMapRotationTooltip": "Karte nach Norden zurücksetzen",
"@resetMapRotationTooltip": {
"description": "Tooltip für Drehung-zurücksetzen-Schaltfläche"
},
"showMapDebugInfo": "Karten-Debug-Info anzeigen",
"@showMapDebugInfo": {
"description": "Umschalter zum Anzeigen von Karten-Debug-Informationen"

View File

@@ -1683,6 +1683,16 @@
"description": "Description for rotate map toggle"
},
"resetMapRotation": "Reset Rotation",
"@resetMapRotation": {
"description": "Button to reset map rotation to north"
},
"resetMapRotationTooltip": "Reset map to north",
"@resetMapRotationTooltip": {
"description": "Tooltip for reset rotation button"
},
"showMapDebugInfo": "Show Map Debug Info",
"@showMapDebugInfo": {
"description": "Toggle for showing map debug information"

View File

@@ -1683,6 +1683,16 @@
"description": "Descripción del alternar de rotar mapa"
},
"resetMapRotation": "Restablecer rotación",
"@resetMapRotation": {
"description": "Botón para restablecer la rotación del mapa al norte"
},
"resetMapRotationTooltip": "Restablecer mapa al norte",
"@resetMapRotationTooltip": {
"description": "Tooltip para botón de restablecer rotación"
},
"showMapDebugInfo": "Mostrar información de depuración del mapa",
"@showMapDebugInfo": {
"description": "Alternar para mostrar información de depuración del mapa"

View File

@@ -1683,6 +1683,16 @@
"description": "Description de l'interrupteur de rotation de la carte"
},
"resetMapRotation": "Réinitialiser la rotation",
"@resetMapRotation": {
"description": "Bouton pour réinitialiser la rotation de la carte vers le nord"
},
"resetMapRotationTooltip": "Réinitialiser la carte vers le nord",
"@resetMapRotationTooltip": {
"description": "Infobulle pour le bouton de réinitialisation de rotation"
},
"showMapDebugInfo": "Afficher les infos de débogage de la carte",
"@showMapDebugInfo": {
"description": "Interrupteur pour afficher les informations de débogage de la carte"

View File

@@ -567,6 +567,10 @@
"mapFollowsDirection": "Karta slijedi vaš smjer pri kretanju",
"resetMapRotation": "Resetiraj rotaciju",
"resetMapRotationTooltip": "Vrati kartu na sjever",
"showMapDebugInfo": "Prikaži debug informacije karte",
"displayZoomLevelBounds": "Prikaži razinu zumiranja i granice",

View File

@@ -1683,6 +1683,16 @@
"description": "Descrizione per l'interruttore ruota mappa"
},
"resetMapRotation": "Ripristina Rotazione",
"@resetMapRotation": {
"description": "Pulsante per ripristinare la rotazione della mappa verso nord"
},
"resetMapRotationTooltip": "Ripristina mappa verso nord",
"@resetMapRotationTooltip": {
"description": "Tooltip per il pulsante di ripristino rotazione"
},
"showMapDebugInfo": "Mostra Info Debug Mappa",
"@showMapDebugInfo": {
"description": "Interruttore per mostrare informazioni di debug della mappa"

View File

@@ -1810,6 +1810,18 @@ abstract class AppLocalizations {
/// **'Map follows your direction when moving'**
String get mapFollowsDirection;
/// Button to reset map rotation to north
///
/// In en, this message translates to:
/// **'Reset Rotation'**
String get resetMapRotation;
/// Tooltip for reset rotation button
///
/// In en, this message translates to:
/// **'Reset map to north'**
String get resetMapRotationTooltip;
/// Toggle for showing map debug information
///
/// In en, this message translates to:

View File

@@ -991,6 +991,12 @@ class AppLocalizationsDe extends AppLocalizations {
String get mapFollowsDirection =>
'Karte folgt Ihrer Richtung während der Bewegung';
@override
String get resetMapRotation => 'Drehung zurücksetzen';
@override
String get resetMapRotationTooltip => 'Karte nach Norden zurücksetzen';
@override
String get showMapDebugInfo => 'Karten-Debug-Info anzeigen';

View File

@@ -987,6 +987,12 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get mapFollowsDirection => 'Map follows your direction when moving';
@override
String get resetMapRotation => 'Reset Rotation';
@override
String get resetMapRotationTooltip => 'Reset map to north';
@override
String get showMapDebugInfo => 'Show Map Debug Info';

View File

@@ -993,6 +993,12 @@ class AppLocalizationsEs extends AppLocalizations {
String get mapFollowsDirection =>
'El mapa sigue tu dirección cuando te mueves';
@override
String get resetMapRotation => 'Restablecer rotación';
@override
String get resetMapRotationTooltip => 'Restablecer mapa al norte';
@override
String get showMapDebugInfo => 'Mostrar información de depuración del mapa';

View File

@@ -995,6 +995,12 @@ class AppLocalizationsFr extends AppLocalizations {
String get mapFollowsDirection =>
'La carte suit votre direction lorsque vous vous déplacez';
@override
String get resetMapRotation => 'Réinitialiser la rotation';
@override
String get resetMapRotationTooltip => 'Réinitialiser la carte vers le nord';
@override
String get showMapDebugInfo => 'Afficher les infos de débogage de la carte';

View File

@@ -985,6 +985,12 @@ class AppLocalizationsHr extends AppLocalizations {
@override
String get mapFollowsDirection => 'Karta slijedi vaš smjer pri kretanju';
@override
String get resetMapRotation => 'Resetiraj rotaciju';
@override
String get resetMapRotationTooltip => 'Vrati kartu na sjever';
@override
String get showMapDebugInfo => 'Prikaži debug informacije karte';

View File

@@ -992,6 +992,12 @@ class AppLocalizationsIt extends AppLocalizations {
String get mapFollowsDirection =>
'La mappa segue la tua direzione quando ti muovi';
@override
String get resetMapRotation => 'Ripristina Rotazione';
@override
String get resetMapRotationTooltip => 'Ripristina mappa verso nord';
@override
String get showMapDebugInfo => 'Mostra Info Debug Mappa';

View File

@@ -985,6 +985,12 @@ class AppLocalizationsSl extends AppLocalizations {
@override
String get mapFollowsDirection => 'Zemljevid sledi vaši smeri pri gibanju';
@override
String get resetMapRotation => 'Ponastavi rotacijo';
@override
String get resetMapRotationTooltip => 'Ponastavi zemljevid na sever';
@override
String get showMapDebugInfo => 'Prikaži debug informacije zemljevida';

View File

@@ -567,6 +567,10 @@
"mapFollowsDirection": "Zemljevid sledi vaši smeri pri gibanju",
"resetMapRotation": "Ponastavi rotacijo",
"resetMapRotationTooltip": "Ponastavi zemljevid na sever",
"showMapDebugInfo": "Prikaži debug informacije zemljevida",
"displayZoomLevelBounds": "Prikaži nivo povečave in meje",

View File

@@ -291,6 +291,9 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
orElse: () => MapLayer.openStreetMap,
);
_currentLayer = mbtilesLayer;
} else if (layerType == MapLayerType.wmsBase) {
// Use Slovenian aerial layer if that's what was saved
_currentLayer = _slovenianAerialLayer;
} else {
// Use default layer
_currentLayer = MapLayer.allLayers.firstWhere(
@@ -299,6 +302,12 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
);
}
}
// Clamp saved zoom if it exceeds the current layer's maximum
// For WMS layers, use a middle zoom (11) instead of max zoom to avoid extreme close-up
if (_savedMapZoom != null && _savedMapZoom! > _currentLayer.maxZoom) {
_savedMapZoom = _currentLayer.isWms ? 11.0 : _currentLayer.maxZoom;
}
});
}
}
@@ -436,6 +445,18 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
}
}
// Reset map rotation to north (0 degrees)
void _resetMapRotation() {
if (!_isMapReady) return;
try {
final camera = _mapController.camera;
_mapController.moveAndRotate(camera.center, camera.zoom, 0);
} catch (e) {
// Silently fail if map controller not ready
debugPrint('Failed to reset map rotation: $e');
}
}
LatLng _calculateCenter(List<Contact> contacts, List<SarMarker> sarMarkers) {
return _markerService.calculateCenter(
contacts: contacts,
@@ -540,6 +561,13 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
onTap: () async {
setState(() {
_currentLayer = layer;
// Clamp zoom level if current zoom exceeds new layer's max
if (_isMapReady && _mapController.camera.zoom > layer.maxZoom) {
_mapController.move(
_mapController.camera.center,
layer.maxZoom,
);
}
});
_saveSettings();
Navigator.pop(context);
@@ -557,6 +585,14 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
onTap: () async {
setState(() {
_currentLayer = _slovenianAerialLayer;
// Clamp zoom level if current zoom exceeds new layer's max
// For WMS layers, use a middle zoom (11) instead of max zoom to avoid extreme close-up
if (_isMapReady && _mapController.camera.zoom > _slovenianAerialLayer.maxZoom) {
_mapController.move(
_mapController.camera.center,
11.0, // Middle zoom for WMS
);
}
});
_saveSettings();
Navigator.pop(context);
@@ -592,6 +628,13 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
setState(() {
_currentLayer = layer;
// Clamp zoom level if current zoom exceeds new layer's max
if (_isMapReady && _mapController.camera.zoom > layer.maxZoom) {
_mapController.move(
_mapController.camera.center,
layer.maxZoom,
);
}
});
_saveSettings();
@@ -601,9 +644,10 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
},
)),
],
// WMS Overlays section (only for Slovenian/Croatian regions)
if (AppLocalizations.of(context)!.localeName == 'sl' ||
AppLocalizations.of(context)!.localeName == 'hr') ...[
// WMS Overlays section (only for Slovenian/Croatian regions and when WMS base layer is selected)
if ((AppLocalizations.of(context)!.localeName == 'sl' ||
AppLocalizations.of(context)!.localeName == 'hr') &&
_currentLayer.isWms) ...[
const Divider(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
@@ -1156,6 +1200,10 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
if (event is MapEventMoveEnd || event is MapEventScrollWheelZoom) {
_saveMapPosition();
}
// Trigger rebuild on rotation change to show/hide reset button
if (event is MapEventRotateEnd || event is MapEventRotateStart) {
setState(() {});
}
},
onLongPress: (tapPosition, point) {
// Handle measurement mode - set measurement points
@@ -1828,6 +1876,13 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
FloatingActionButton.small(
heroTag: 'center_map',
onPressed: !_isMapReady ? null : () async {
// First tap: reset rotation if not 0
// Second tap (or if rotation is 0): jump to current location
if (_getMapRotation() != 0) {
_resetMapRotation();
return;
}
// Force update GPS location and jump to it
final position = await _locationService.getCurrentPosition();
if (position != null && mounted) {

View File

@@ -8,6 +8,7 @@ import '../providers/contacts_provider.dart';
import '../providers/map_provider.dart';
import '../providers/connection_provider.dart';
import '../providers/drawing_provider.dart';
import '../providers/app_provider.dart';
import '../models/message.dart';
import '../models/contact.dart';
import '../models/sar_marker.dart';
@@ -564,20 +565,25 @@ class _MessagesTabState extends State<MessagesTab> {
// Get all recent messages
final allMessages = messagesProvider.getRecentMessages(count: 100);
// Get simple mode setting from AppProvider
final appProvider = context.read<AppProvider>();
final isSimpleMode = appProvider.isSimpleMode;
List<Message> filteredMessages;
// If public channel is selected, show ALL messages
if (_destinationType ==
MessageDestinationPreferences.destinationTypeChannel &&
_selectedRecipient == null) {
return allMessages;
filteredMessages = allMessages;
}
// If a contact or room is selected, filter by recipient
if ((_destinationType ==
else if ((_destinationType ==
MessageDestinationPreferences.destinationTypeContact ||
_destinationType ==
MessageDestinationPreferences.destinationTypeRoom) &&
_selectedRecipient != null) {
return allMessages.where((message) {
filteredMessages = allMessages.where((message) {
// Include messages sent TO this recipient
if (message.recipientPublicKey != null &&
message.recipientPublicKey!.length >= 6 &&
@@ -603,10 +609,19 @@ class _MessagesTabState extends State<MessagesTab> {
return false;
}).toList();
} else {
// Default: show all messages (fallback case)
filteredMessages = allMessages;
}
// Default: show all messages (fallback case)
return allMessages;
// In simple mode, filter out system messages (toast logs)
if (isSimpleMode) {
filteredMessages = filteredMessages
.where((message) => !message.isSystemMessage)
.toList();
}
return filteredMessages;
}
@override