From 2a909e60813ee2427c8bd7e0892bcae1010ee157 Mon Sep 17 00:00:00 2001 From: Winston Lowe Date: Sat, 7 Feb 2026 19:45:02 -0800 Subject: [PATCH] Enhance GPX export functionality with customizable parameters and improved metadata --- lib/l10n/app_en.arb | 17 ++++++++---- lib/screens/settings_screen.dart | 47 ++++++++++++++++++++++++++++---- lib/utils/gpx_export.dart | 23 ++++++++++------ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8f501e0..18b5c6c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1345,14 +1345,19 @@ "contacts_contactAdvertCopied": "Advert copied to Clipboard.", "contacts_contactAdvertCopyFailed": "Copying advert to Clipboard failed.", - "settings_gpxExportRepeaters": "Export repeaters to GPX", - "settings_gpxExportRepeatersSubtitle": "Exports repeaters with a location to GPX file.", - "settings_gpxExportContacts": "Export contacts to GPX", - "settings_gpxExportContactsSubtitle": "Exports chat contacts with a location to GPX file.", - "settings_gpxExportAll": "Export all to GPX", + "settings_gpxExportRepeaters": "Export repeaters / room server to GPX", + "settings_gpxExportRepeatersSubtitle": "Exports repeaters / roomserver with a location to GPX file.", + "settings_gpxExportContacts": "Export companions to GPX", + "settings_gpxExportContactsSubtitle": "Exports companions with a location to GPX file.", + "settings_gpxExportAll": "Export all contacts to GPX", "settings_gpxExportAllSubtitle": "Exports all contacts with a location to GPX file.", "settings_gpxExportSuccess": "Successfully exported GPX file.", "settings_gpxExportNoContacts": "No contacts to export.", "settings_gpxExportNotAvailable": "Not supported on your device/OS", - "settings_gpxExportError": "There was an error when exporting." + "settings_gpxExportError": "There was an error when exporting.", + "settings_gpxExportRepeatersRoom": "Repeater & room server locations", + "settings_gpxExportChat": "Companion locations", + "settings_gpxExportAllContacts": "All contacts locations", + "settings_gpxExportShareText": "Map data exported from meshcore-open", + "settings_gpxExportShareSubject": "meshcore-open GPX map data export" } diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 6dfbc0a..2212b8d 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -688,9 +688,22 @@ class _SettingsScreenState extends State { ); } - _gpxExport(GpxExport exporter) async { + _gpxExport( + GpxExport exporter, + String name, + String description, + String filename, + String shareText, + String subject, + ) async { final l10n = context.l10n; - final result = await exporter.exportGPX(); + final result = await exporter.exportGPX( + name, + description, + filename, + shareText, + subject, + ); if (!mounted) return; switch (result) { case gpxExportSuccess: @@ -701,14 +714,17 @@ class _SettingsScreenState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.settings_gpxExportNoContacts)), ); + break; case gpxExportNotAvailable: ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.settings_gpxExportNotAvailable)), ); + break; case gpxExportFailed: ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(l10n.settings_gpxExportError))); + break; } } @@ -725,7 +741,14 @@ class _SettingsScreenState extends State { onTap: () async { final exporter = GpxExport(connector); exporter.addRepeaters(); - _gpxExport(exporter); + _gpxExport( + exporter, + l10n.map_repeater, + l10n.settings_gpxExportRepeatersRoom, + "meshcore_repeaters_", + l10n.settings_gpxExportShareText, + l10n.settings_gpxExportShareSubject, + ); }, ), ListTile( @@ -736,7 +759,14 @@ class _SettingsScreenState extends State { onTap: () async { final exporter = GpxExport(connector); exporter.addContacts(); - _gpxExport(exporter); + _gpxExport( + exporter, + l10n.map_repeater, + l10n.settings_gpxExportChat, + "meshcore_contacts_", + l10n.settings_gpxExportShareText, + l10n.settings_gpxExportShareSubject, + ); }, ), ListTile( @@ -747,7 +777,14 @@ class _SettingsScreenState extends State { onTap: () async { final exporter = GpxExport(connector); exporter.addAll(); - _gpxExport(exporter); + _gpxExport( + exporter, + l10n.map_repeater, + l10n.settings_gpxExportAllContacts, + "meshcore_all_", + l10n.settings_gpxExportShareText, + l10n.settings_gpxExportShareSubject, + ); }, ), ], diff --git a/lib/utils/gpx_export.dart b/lib/utils/gpx_export.dart index 995f34c..92494c9 100644 --- a/lib/utils/gpx_export.dart +++ b/lib/utils/gpx_export.dart @@ -102,7 +102,13 @@ class GpxExport { } } - Future exportGPX() async { + Future exportGPX( + String name, + String description, + String filename, + String shareText, + String subject, + ) async { if (_contacts.isEmpty) { debugPrint("No repeaters to export – nothing to share."); return gpxExportNoContacts; @@ -112,10 +118,10 @@ class GpxExport { // 1. Build GPX content (your existing logic – unchanged here) final gpx = Gpx() ..version = '1.1' - ..creator = 'meshcore-open Repeater Exporter' + ..creator = 'meshcore-open exporter' ..metadata = Metadata( - name: 'Meshcore Repeaters', - desc: 'Repeater & room locations exported from meshcore-open', + name: name, + desc: description, time: DateTime.now().toUtc(), ); @@ -142,7 +148,9 @@ class GpxExport { .replaceAll('.', '-') .split('T') .join('_'); - final path = '${dir.path}/meshcore_repeaters_$timestamp.gpx'; + + // ignore: unnecessary_string_escapes + final path = '${dir.path}/$filename$timestamp.gpx'; final file = File(path); await file.writeAsString(xml); @@ -150,9 +158,8 @@ class GpxExport { // 3. Modern share call (2025+ style) final result = await SharePlus.instance.share( ShareParams( - text: - 'Repeater locations exported from meshcore-open app as GPX file.', - subject: 'Meshcore Repeaters GPX Export', + text: shareText, + subject: subject, files: [XFile(path)], // Optional: sharePositionOrigin: ... (if you want iPad popover positioning) ),