consolidate parsing in single parseMarkerText in map_screen.dart

This commit is contained in:
ericz
2026-04-26 01:23:33 +02:00
parent 7db3a12723
commit 94d9afe8b1
3 changed files with 33 additions and 92 deletions
+4 -33
View File
@@ -4,7 +4,6 @@ import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';
import '../connector/meshcore_connector.dart';
@@ -357,7 +356,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
final enableTracing = settingsService.settings.enableMessageTracing;
final isOutgoing = message.isOutgoing;
final gifId = GifHelper.parseGif(message.text);
final poi = _parsePoiMessage(message.text);
final poi = parseMarkerText(message.text);
final translatedDisplayText =
message.translatedText != null &&
message.translatedText!.trim().isNotEmpty
@@ -702,7 +701,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
final previewTextColor = colorScheme.onSurface.withValues(alpha: 0.7);
final gifId = GifHelper.parseGif(replyText);
final poi = _parsePoiMessage(replyText);
final poi = parseMarkerText(replyText);
Widget contentPreview;
if (gifId != null) {
@@ -813,23 +812,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
);
}
_PoiInfo? _parsePoiMessage(String text) {
final trimmed = text.trim();
final match = RegExp(
r'm:([\-0-9.]+),([\-0-9.]+)\|([^|]*)\|(.*)',
).firstMatch(trimmed);
if (match == null) return null;
final lat = double.tryParse(match.group(1) ?? '');
final lon = double.tryParse(match.group(2) ?? '');
if (lat == null || lon == null) return null;
final label = match.group(3) ?? '';
final flags = match.group(4) ?? '';
return _PoiInfo(lat: lat, lon: lon, label: label, flags: flags);
}
Widget _buildPoiMessage(
BuildContext context,
_PoiInfo poi,
MarkerPayload poi,
bool isOutgoing,
double textScale,
String senderName, {
@@ -865,7 +850,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
context,
MaterialPageRoute(
builder: (context) => MapScreen(
highlightPosition: LatLng(poi.lat, poi.lon),
highlightPosition: poi.position,
highlightLabel: poi.label,
highlightMarkerKey: key,
),
@@ -1520,17 +1505,3 @@ class _SwipeReplyBubbleState extends State<_SwipeReplyBubble> {
);
}
}
class _PoiInfo {
final double lat;
final double lon;
final String label;
final String flags;
const _PoiInfo({
required this.lat,
required this.lon,
required this.label,
required this.flags,
});
}
+3 -32
View File
@@ -9,7 +9,6 @@ import 'package:meshcore_open/screens/path_trace_map.dart';
import 'package:provider/provider.dart';
import '../utils/platform_info.dart';
import 'package:latlong2/latlong.dart';
import '../connector/meshcore_connector.dart';
import '../connector/meshcore_protocol.dart';
@@ -1589,7 +1588,7 @@ class _MessageBubble extends StatelessWidget {
final isOutgoing = message.isOutgoing;
final colorScheme = Theme.of(context).colorScheme;
final gifId = GifHelper.parseGif(message.text);
final poi = _parsePoiMessage(message.text);
final poi = parseMarkerText(message.text);
final isFailed = message.status == MessageStatus.failed;
final bubbleColor = isFailed
? colorScheme.errorContainer
@@ -1863,23 +1862,9 @@ class _MessageBubble extends StatelessWidget {
);
}
_PoiInfo? _parsePoiMessage(String text) {
final trimmed = text.trim();
final match = RegExp(
r'^m:([\-0-9.]+),([\-0-9.]+)\|([^|]*)\|(.*)$',
).firstMatch(trimmed);
if (match == null) return null;
final lat = double.tryParse(match.group(1) ?? '');
final lon = double.tryParse(match.group(2) ?? '');
if (lat == null || lon == null) return null;
final label = match.group(3) ?? '';
final flags = match.group(4) ?? '';
return _PoiInfo(lat: lat, lon: lon, label: label, flags: flags);
}
Widget _buildPoiMessage(
BuildContext context,
_PoiInfo poi,
MarkerPayload poi,
Color textColor,
Color metaColor,
double textScale,
@@ -1907,7 +1892,7 @@ class _MessageBubble extends StatelessWidget {
context,
MaterialPageRoute(
builder: (context) => MapScreen(
highlightPosition: LatLng(poi.lat, poi.lon),
highlightPosition: poi.position,
highlightLabel: poi.label,
highlightMarkerKey: key,
),
@@ -2090,17 +2075,3 @@ class _MessageBubble extends StatelessWidget {
return '$hour:$minute';
}
}
class _PoiInfo {
final double lat;
final double lon;
final String label;
final String flags;
const _PoiInfo({
required this.lat,
required this.lon,
required this.label,
required this.flags,
});
}
+26 -27
View File
@@ -1286,7 +1286,7 @@ class _MapScreenState extends State<MapScreen> {
for (final contact in connector.contacts) {
final messages = connector.getMessages(contact);
for (final message in messages) {
final payload = _parseMarkerText(message.text);
final payload = parseMarkerText(message.text);
if (payload == null) continue;
final fromName = message.isOutgoing ? selfName : contact.name;
final key = buildSharedMarkerKey(
@@ -1300,7 +1300,9 @@ class _MapScreenState extends State<MapScreen> {
_SharedMarker(
id: key,
position: payload.position,
label: payload.label,
label: payload.label.isEmpty
? context.l10n.map_sharedPin
: payload.label,
flags: payload.flags,
fromName: fromName,
sourceLabel: contact.name,
@@ -1316,7 +1318,7 @@ class _MapScreenState extends State<MapScreen> {
final isPublic = _isPublicChannel(channel);
final messages = connector.getChannelMessages(channel);
for (final message in messages) {
final payload = _parseMarkerText(message.text);
final payload = parseMarkerText(message.text);
if (payload == null) continue;
final key = buildSharedMarkerKey(
sourceId: 'channel:${channel.index}',
@@ -1329,7 +1331,9 @@ class _MapScreenState extends State<MapScreen> {
_SharedMarker(
id: key,
position: payload.position,
label: payload.label,
label: payload.label.isEmpty
? context.l10n.map_sharedPin
: payload.label,
flags: payload.flags,
fromName: message.senderName,
sourceLabel: channel.name.isEmpty
@@ -1364,27 +1368,6 @@ class _MapScreenState extends State<MapScreen> {
return markers;
}
_MarkerPayload? _parseMarkerText(String text) {
final trimmed = text.trim();
if (!trimmed.startsWith('m:')) return null;
final parts = trimmed.substring(2).split('|');
if (parts.isEmpty) return null;
final coords = parts[0].split(',');
if (coords.length != 2) return null;
final lat = double.tryParse(coords[0].trim());
final lon = double.tryParse(coords[1].trim());
if (lat == null || lon == null) return null;
final label = parts.length > 1 ? parts[1].trim() : '';
final flags = parts.length > 2 ? parts[2].trim() : '';
return _MarkerPayload(
position: LatLng(lat, lon),
label: label.isEmpty ? context.l10n.map_sharedPin : label,
flags: flags,
);
}
Marker _buildSharedMarker(_SharedMarker marker) {
final markerColor = marker.isChannel
? (marker.isPublicChannel ? Colors.orange : Colors.purple)
@@ -2385,18 +2368,34 @@ class _GuessedLocation {
});
}
class _MarkerPayload {
class MarkerPayload {
final LatLng position;
final String label;
final String flags;
_MarkerPayload({
MarkerPayload({
required this.position,
required this.label,
required this.flags,
});
}
/// Parse a shared marker text message of the form
/// `m:<lat>,<lon>|<label>|<flags>` and return a [MarkerPayload].
MarkerPayload? parseMarkerText(String text) {
final trimmed = text.trim();
final match = RegExp(
r'm:([\-0-9.]+),([\-0-9.]+)\|([^|]*)\|(.*)',
).firstMatch(trimmed);
if (match == null) return null;
final lat = double.tryParse(match.group(1) ?? '');
final lon = double.tryParse(match.group(2) ?? '');
if (lat == null || lon == null) return null;
final label = (match.group(3) ?? '').trim();
final flags = (match.group(4) ?? '').trim();
return MarkerPayload(position: LatLng(lat, lon), label: label, flags: flags);
}
/// Build a normalized dedupe key for shared markers.
/// Keeps the same algorithm previously present in both chat and map screens.
String buildSharedMarkerKey({