From cec092b8c099ae1468801aea5ea103f66cc14284 Mon Sep 17 00:00:00 2001 From: Janez T Date: Sun, 26 Oct 2025 17:22:39 +0100 Subject: [PATCH] feat: Add functionality to save SAR messages as templates with corresponding localization --- lib/l10n/app_en.arb | 15 ++++++ lib/l10n/app_hr.arb | 3 ++ lib/l10n/app_localizations.dart | 18 ++++++++ lib/l10n/app_localizations_de.dart | 9 ++++ lib/l10n/app_localizations_en.dart | 9 ++++ lib/l10n/app_localizations_es.dart | 9 ++++ lib/l10n/app_localizations_fr.dart | 9 ++++ lib/l10n/app_localizations_hr.dart | 9 ++++ lib/l10n/app_localizations_it.dart | 9 ++++ lib/l10n/app_localizations_sl.dart | 9 ++++ lib/l10n/app_sl.arb | 3 ++ lib/screens/messages_tab.dart | 74 ++++++++++++++++++++++++++++++ 12 files changed, 176 insertions(+) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 173a337..a9ab97f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1830,6 +1830,21 @@ "description": "Success message when text is copied" }, + "saveAsTemplate": "Save as Template", + "@saveAsTemplate": { + "description": "Option to save SAR message as a reusable template" + }, + + "templateSaved": "Template saved successfully", + "@templateSaved": { + "description": "Success message when SAR template is saved" + }, + + "templateAlreadyExists": "Template with this emoji already exists", + "@templateAlreadyExists": { + "description": "Error message when trying to save duplicate template" + }, + "deleteMessage": "Delete message", "@deleteMessage": { "description": "Dialog title for deleting a message" diff --git a/lib/l10n/app_hr.arb b/lib/l10n/app_hr.arb index 3df7f9d..0deed2a 100644 --- a/lib/l10n/app_hr.arb +++ b/lib/l10n/app_hr.arb @@ -636,6 +636,9 @@ "messageDeleted": "Poruka izbrisana", "copyText": "Kopiraj tekst", "textCopiedToClipboard": "Tekst kopiran u međuspremnik", + "saveAsTemplate": "Spremi kao predložak", + "templateSaved": "Predložak uspješno spremljen", + "templateAlreadyExists": "Predložak s ovim emojijem već postoji", "deleteMessage": "Izbriši poruku", "deleteMessageConfirmation": "Jeste li sigurni da želite izbrisati ovu poruku?", "shareLocation": "Podijeli lokaciju", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index d8539df..9fbe42b 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1954,6 +1954,24 @@ abstract class AppLocalizations { /// **'Copy text'** String get copyText; + /// Option to save SAR message as a reusable template + /// + /// In en, this message translates to: + /// **'Save as Template'** + String get saveAsTemplate; + + /// Success message when SAR template is saved + /// + /// In en, this message translates to: + /// **'Template saved successfully'** + String get templateSaved; + + /// Error message when trying to save duplicate template + /// + /// In en, this message translates to: + /// **'Template with this emoji already exists'** + String get templateAlreadyExists; + /// Dialog title for deleting a message /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 623b5b3..7fca81c 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1078,6 +1078,15 @@ class AppLocalizationsDe extends AppLocalizations { @override String get copyText => 'Text kopieren'; + @override + String get saveAsTemplate => 'Save as Template'; + + @override + String get templateSaved => 'Template saved successfully'; + + @override + String get templateAlreadyExists => 'Template with this emoji already exists'; + @override String get deleteMessage => 'Nachricht löschen'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 9dd83cf..11ca265 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1068,6 +1068,15 @@ class AppLocalizationsEn extends AppLocalizations { @override String get copyText => 'Copy text'; + @override + String get saveAsTemplate => 'Save as Template'; + + @override + String get templateSaved => 'Template saved successfully'; + + @override + String get templateAlreadyExists => 'Template with this emoji already exists'; + @override String get deleteMessage => 'Delete message'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 5417f7a..edb9f76 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1074,6 +1074,15 @@ class AppLocalizationsEs extends AppLocalizations { @override String get copyText => 'Copiar texto'; + @override + String get saveAsTemplate => 'Save as Template'; + + @override + String get templateSaved => 'Template saved successfully'; + + @override + String get templateAlreadyExists => 'Template with this emoji already exists'; + @override String get deleteMessage => 'Eliminar mensaje'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 92dfefd..833bcd6 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1079,6 +1079,15 @@ class AppLocalizationsFr extends AppLocalizations { @override String get copyText => 'Copier le texte'; + @override + String get saveAsTemplate => 'Save as Template'; + + @override + String get templateSaved => 'Template saved successfully'; + + @override + String get templateAlreadyExists => 'Template with this emoji already exists'; + @override String get deleteMessage => 'Supprimer le message'; diff --git a/lib/l10n/app_localizations_hr.dart b/lib/l10n/app_localizations_hr.dart index 0834150..f9a2c49 100644 --- a/lib/l10n/app_localizations_hr.dart +++ b/lib/l10n/app_localizations_hr.dart @@ -1070,6 +1070,15 @@ class AppLocalizationsHr extends AppLocalizations { @override String get copyText => 'Kopiraj tekst'; + @override + String get saveAsTemplate => 'Spremi kao predložak'; + + @override + String get templateSaved => 'Predložak uspješno spremljen'; + + @override + String get templateAlreadyExists => 'Predložak s ovim emojijem već postoji'; + @override String get deleteMessage => 'Izbriši poruku'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 0c5e79f..46f5838 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -1076,6 +1076,15 @@ class AppLocalizationsIt extends AppLocalizations { @override String get copyText => 'Copia testo'; + @override + String get saveAsTemplate => 'Save as Template'; + + @override + String get templateSaved => 'Template saved successfully'; + + @override + String get templateAlreadyExists => 'Template with this emoji already exists'; + @override String get deleteMessage => 'Elimina messaggio'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index bce6b09..83b57a0 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -1070,6 +1070,15 @@ class AppLocalizationsSl extends AppLocalizations { @override String get copyText => 'Kopiraj besedilo'; + @override + String get saveAsTemplate => 'Shrani kot predlogo'; + + @override + String get templateSaved => 'Predloga uspešno shranjena'; + + @override + String get templateAlreadyExists => 'Predloga s tem emojijem že obstaja'; + @override String get deleteMessage => 'Izbriši sporočilo'; diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 1d36936..11f28d0 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -636,6 +636,9 @@ "messageDeleted": "Sporočilo izbrisano", "copyText": "Kopiraj besedilo", "textCopiedToClipboard": "Besedilo kopirano v odložišče", + "saveAsTemplate": "Shrani kot predlogo", + "templateSaved": "Predloga uspešno shranjena", + "templateAlreadyExists": "Predloga s tem emojijem že obstaja", "deleteMessage": "Izbriši sporočilo", "deleteMessageConfirmation": "Ali ste prepričani, da želite izbrisati to sporočilo?", "shareLocation": "Deli lokacijo", diff --git a/lib/screens/messages_tab.dart b/lib/screens/messages_tab.dart index 6f98b26..1e28495 100644 --- a/lib/screens/messages_tab.dart +++ b/lib/screens/messages_tab.dart @@ -11,13 +11,16 @@ import '../providers/drawing_provider.dart'; import '../models/message.dart'; import '../models/contact.dart'; import '../models/sar_marker.dart'; +import '../models/sar_template.dart'; import '../models/map_drawing.dart'; import '../widgets/messages/sar_update_sheet.dart'; import '../widgets/messages/recipient_selector_sheet.dart'; import '../widgets/contacts/direct_message_sheet.dart'; import '../widgets/drawing_minimap_preview.dart'; import '../services/message_destination_preferences.dart'; +import '../services/sar_template_service.dart'; import '../utils/toast_logger.dart'; +import '../utils/sar_message_parser.dart'; import '../l10n/app_localizations.dart'; import '../utils/message_extensions.dart'; @@ -966,6 +969,35 @@ class _MessageBubble extends StatelessWidget { ); }, ), + // Save as Template option (only for SAR markers without existing template) + if (message.isSarMarker) + Builder( + builder: (context) { + // Extract emoji from SAR message + final sarInfo = SarMessageParser.parse(message.text); + if (sarInfo == null || sarInfo.emoji.isEmpty) { + return const SizedBox.shrink(); + } + + // Check if template with this emoji already exists + final sarTemplateService = SarTemplateService(); + final templateExists = sarTemplateService.templates + .any((t) => t.emoji == sarInfo.emoji); + + if (templateExists) { + return const SizedBox.shrink(); + } + + return ListTile( + leading: const Icon(Icons.bookmark_add), + title: Text(AppLocalizations.of(context)!.saveAsTemplate), + onTap: () { + Navigator.pop(context); + _saveAsTemplate(context); + }, + ); + }, + ), // Share location option (only for SAR markers with GPS coordinates) if (message.isSarMarker && message.sarGpsCoordinates != null) ListTile( @@ -1215,6 +1247,48 @@ class _MessageBubble extends StatelessWidget { ); } + Future _saveAsTemplate(BuildContext context) async { + if (!message.isSarMarker) { + ToastLogger.error(context, 'Not a SAR marker'); + return; + } + + try { + // Parse the SAR message to create a template + final template = SarTemplate.fromSarMessage(message.text); + + // Get SAR template service + final sarTemplateService = SarTemplateService(); + + // Check if template with this emoji already exists + final existingTemplates = sarTemplateService.templates + .where((t) => t.emoji == template.emoji) + .toList(); + + if (existingTemplates.isNotEmpty) { + if (!context.mounted) return; + ToastLogger.warning( + context, + AppLocalizations.of(context)!.templateAlreadyExists, + ); + return; + } + + // Save the template + await sarTemplateService.addTemplate(template); + + if (!context.mounted) return; + ToastLogger.success( + context, + AppLocalizations.of(context)!.templateSaved, + ); + } catch (e) { + debugPrint('Error saving template: $e'); + if (!context.mounted) return; + ToastLogger.error(context, 'Failed to save template: $e'); + } + } + @override Widget build(BuildContext context) { final isSarMarker = message.isSarMarker;