Enhance GPX export functionality with customizable parameters and improved metadata

This commit is contained in:
Winston Lowe
2026-02-07 19:45:02 -08:00
parent d1009d3c20
commit 2a909e6081
3 changed files with 68 additions and 19 deletions
+11 -6
View File
@@ -1345,14 +1345,19 @@
"contacts_contactAdvertCopied": "Advert copied to Clipboard.", "contacts_contactAdvertCopied": "Advert copied to Clipboard.",
"contacts_contactAdvertCopyFailed": "Copying advert to Clipboard failed.", "contacts_contactAdvertCopyFailed": "Copying advert to Clipboard failed.",
"settings_gpxExportRepeaters": "Export repeaters to GPX", "settings_gpxExportRepeaters": "Export repeaters / room server to GPX",
"settings_gpxExportRepeatersSubtitle": "Exports repeaters with a location to GPX file.", "settings_gpxExportRepeatersSubtitle": "Exports repeaters / roomserver with a location to GPX file.",
"settings_gpxExportContacts": "Export contacts to GPX", "settings_gpxExportContacts": "Export companions to GPX",
"settings_gpxExportContactsSubtitle": "Exports chat contacts with a location to GPX file.", "settings_gpxExportContactsSubtitle": "Exports companions with a location to GPX file.",
"settings_gpxExportAll": "Export all to GPX", "settings_gpxExportAll": "Export all contacts to GPX",
"settings_gpxExportAllSubtitle": "Exports all contacts with a location to GPX file.", "settings_gpxExportAllSubtitle": "Exports all contacts with a location to GPX file.",
"settings_gpxExportSuccess": "Successfully exported GPX file.", "settings_gpxExportSuccess": "Successfully exported GPX file.",
"settings_gpxExportNoContacts": "No contacts to export.", "settings_gpxExportNoContacts": "No contacts to export.",
"settings_gpxExportNotAvailable": "Not supported on your device/OS", "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"
} }
+42 -5
View File
@@ -688,9 +688,22 @@ class _SettingsScreenState extends State<SettingsScreen> {
); );
} }
_gpxExport(GpxExport exporter) async { _gpxExport(
GpxExport exporter,
String name,
String description,
String filename,
String shareText,
String subject,
) async {
final l10n = context.l10n; final l10n = context.l10n;
final result = await exporter.exportGPX(); final result = await exporter.exportGPX(
name,
description,
filename,
shareText,
subject,
);
if (!mounted) return; if (!mounted) return;
switch (result) { switch (result) {
case gpxExportSuccess: case gpxExportSuccess:
@@ -701,14 +714,17 @@ class _SettingsScreenState extends State<SettingsScreen> {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.settings_gpxExportNoContacts)), SnackBar(content: Text(l10n.settings_gpxExportNoContacts)),
); );
break;
case gpxExportNotAvailable: case gpxExportNotAvailable:
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.settings_gpxExportNotAvailable)), SnackBar(content: Text(l10n.settings_gpxExportNotAvailable)),
); );
break;
case gpxExportFailed: case gpxExportFailed:
ScaffoldMessenger.of( ScaffoldMessenger.of(
context, context,
).showSnackBar(SnackBar(content: Text(l10n.settings_gpxExportError))); ).showSnackBar(SnackBar(content: Text(l10n.settings_gpxExportError)));
break;
} }
} }
@@ -725,7 +741,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
onTap: () async { onTap: () async {
final exporter = GpxExport(connector); final exporter = GpxExport(connector);
exporter.addRepeaters(); exporter.addRepeaters();
_gpxExport(exporter); _gpxExport(
exporter,
l10n.map_repeater,
l10n.settings_gpxExportRepeatersRoom,
"meshcore_repeaters_",
l10n.settings_gpxExportShareText,
l10n.settings_gpxExportShareSubject,
);
}, },
), ),
ListTile( ListTile(
@@ -736,7 +759,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
onTap: () async { onTap: () async {
final exporter = GpxExport(connector); final exporter = GpxExport(connector);
exporter.addContacts(); exporter.addContacts();
_gpxExport(exporter); _gpxExport(
exporter,
l10n.map_repeater,
l10n.settings_gpxExportChat,
"meshcore_contacts_",
l10n.settings_gpxExportShareText,
l10n.settings_gpxExportShareSubject,
);
}, },
), ),
ListTile( ListTile(
@@ -747,7 +777,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
onTap: () async { onTap: () async {
final exporter = GpxExport(connector); final exporter = GpxExport(connector);
exporter.addAll(); exporter.addAll();
_gpxExport(exporter); _gpxExport(
exporter,
l10n.map_repeater,
l10n.settings_gpxExportAllContacts,
"meshcore_all_",
l10n.settings_gpxExportShareText,
l10n.settings_gpxExportShareSubject,
);
}, },
), ),
], ],
+15 -8
View File
@@ -102,7 +102,13 @@ class GpxExport {
} }
} }
Future<int> exportGPX() async { Future<int> exportGPX(
String name,
String description,
String filename,
String shareText,
String subject,
) async {
if (_contacts.isEmpty) { if (_contacts.isEmpty) {
debugPrint("No repeaters to export nothing to share."); debugPrint("No repeaters to export nothing to share.");
return gpxExportNoContacts; return gpxExportNoContacts;
@@ -112,10 +118,10 @@ class GpxExport {
// 1. Build GPX content (your existing logic unchanged here) // 1. Build GPX content (your existing logic unchanged here)
final gpx = Gpx() final gpx = Gpx()
..version = '1.1' ..version = '1.1'
..creator = 'meshcore-open Repeater Exporter' ..creator = 'meshcore-open exporter'
..metadata = Metadata( ..metadata = Metadata(
name: 'Meshcore Repeaters', name: name,
desc: 'Repeater & room locations exported from meshcore-open', desc: description,
time: DateTime.now().toUtc(), time: DateTime.now().toUtc(),
); );
@@ -142,7 +148,9 @@ class GpxExport {
.replaceAll('.', '-') .replaceAll('.', '-')
.split('T') .split('T')
.join('_'); .join('_');
final path = '${dir.path}/meshcore_repeaters_$timestamp.gpx';
// ignore: unnecessary_string_escapes
final path = '${dir.path}/$filename$timestamp.gpx';
final file = File(path); final file = File(path);
await file.writeAsString(xml); await file.writeAsString(xml);
@@ -150,9 +158,8 @@ class GpxExport {
// 3. Modern share call (2025+ style) // 3. Modern share call (2025+ style)
final result = await SharePlus.instance.share( final result = await SharePlus.instance.share(
ShareParams( ShareParams(
text: text: shareText,
'Repeater locations exported from meshcore-open app as GPX file.', subject: subject,
subject: 'Meshcore Repeaters GPX Export',
files: [XFile(path)], files: [XFile(path)],
// Optional: sharePositionOrigin: ... (if you want iPad popover positioning) // Optional: sharePositionOrigin: ... (if you want iPad popover positioning)
), ),