feat: Add functionality to save SAR messages as templates with corresponding localization

This commit is contained in:
Janez T
2025-10-26 17:22:39 +01:00
parent a6fbc10221
commit cec092b8c0
12 changed files with 176 additions and 0 deletions

View File

@@ -1830,6 +1830,21 @@
"description": "Success message when text is copied" "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": "Delete message",
"@deleteMessage": { "@deleteMessage": {
"description": "Dialog title for deleting a message" "description": "Dialog title for deleting a message"

View File

@@ -636,6 +636,9 @@
"messageDeleted": "Poruka izbrisana", "messageDeleted": "Poruka izbrisana",
"copyText": "Kopiraj tekst", "copyText": "Kopiraj tekst",
"textCopiedToClipboard": "Tekst kopiran u međuspremnik", "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", "deleteMessage": "Izbriši poruku",
"deleteMessageConfirmation": "Jeste li sigurni da želite izbrisati ovu poruku?", "deleteMessageConfirmation": "Jeste li sigurni da želite izbrisati ovu poruku?",
"shareLocation": "Podijeli lokaciju", "shareLocation": "Podijeli lokaciju",

View File

@@ -1954,6 +1954,24 @@ abstract class AppLocalizations {
/// **'Copy text'** /// **'Copy text'**
String get copyText; 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 /// Dialog title for deleting a message
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View File

@@ -1078,6 +1078,15 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get copyText => 'Text kopieren'; 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 @override
String get deleteMessage => 'Nachricht löschen'; String get deleteMessage => 'Nachricht löschen';

View File

@@ -1068,6 +1068,15 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get copyText => 'Copy text'; 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 @override
String get deleteMessage => 'Delete message'; String get deleteMessage => 'Delete message';

View File

@@ -1074,6 +1074,15 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String get copyText => 'Copiar texto'; 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 @override
String get deleteMessage => 'Eliminar mensaje'; String get deleteMessage => 'Eliminar mensaje';

View File

@@ -1079,6 +1079,15 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String get copyText => 'Copier le texte'; 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 @override
String get deleteMessage => 'Supprimer le message'; String get deleteMessage => 'Supprimer le message';

View File

@@ -1070,6 +1070,15 @@ class AppLocalizationsHr extends AppLocalizations {
@override @override
String get copyText => 'Kopiraj tekst'; 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 @override
String get deleteMessage => 'Izbriši poruku'; String get deleteMessage => 'Izbriši poruku';

View File

@@ -1076,6 +1076,15 @@ class AppLocalizationsIt extends AppLocalizations {
@override @override
String get copyText => 'Copia testo'; 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 @override
String get deleteMessage => 'Elimina messaggio'; String get deleteMessage => 'Elimina messaggio';

View File

@@ -1070,6 +1070,15 @@ class AppLocalizationsSl extends AppLocalizations {
@override @override
String get copyText => 'Kopiraj besedilo'; 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 @override
String get deleteMessage => 'Izbriši sporočilo'; String get deleteMessage => 'Izbriši sporočilo';

View File

@@ -636,6 +636,9 @@
"messageDeleted": "Sporočilo izbrisano", "messageDeleted": "Sporočilo izbrisano",
"copyText": "Kopiraj besedilo", "copyText": "Kopiraj besedilo",
"textCopiedToClipboard": "Besedilo kopirano v odložišče", "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", "deleteMessage": "Izbriši sporočilo",
"deleteMessageConfirmation": "Ali ste prepričani, da želite izbrisati to sporočilo?", "deleteMessageConfirmation": "Ali ste prepričani, da želite izbrisati to sporočilo?",
"shareLocation": "Deli lokacijo", "shareLocation": "Deli lokacijo",

View File

@@ -11,13 +11,16 @@ import '../providers/drawing_provider.dart';
import '../models/message.dart'; import '../models/message.dart';
import '../models/contact.dart'; import '../models/contact.dart';
import '../models/sar_marker.dart'; import '../models/sar_marker.dart';
import '../models/sar_template.dart';
import '../models/map_drawing.dart'; import '../models/map_drawing.dart';
import '../widgets/messages/sar_update_sheet.dart'; import '../widgets/messages/sar_update_sheet.dart';
import '../widgets/messages/recipient_selector_sheet.dart'; import '../widgets/messages/recipient_selector_sheet.dart';
import '../widgets/contacts/direct_message_sheet.dart'; import '../widgets/contacts/direct_message_sheet.dart';
import '../widgets/drawing_minimap_preview.dart'; import '../widgets/drawing_minimap_preview.dart';
import '../services/message_destination_preferences.dart'; import '../services/message_destination_preferences.dart';
import '../services/sar_template_service.dart';
import '../utils/toast_logger.dart'; import '../utils/toast_logger.dart';
import '../utils/sar_message_parser.dart';
import '../l10n/app_localizations.dart'; import '../l10n/app_localizations.dart';
import '../utils/message_extensions.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) // Share location option (only for SAR markers with GPS coordinates)
if (message.isSarMarker && message.sarGpsCoordinates != null) if (message.isSarMarker && message.sarGpsCoordinates != null)
ListTile( ListTile(
@@ -1215,6 +1247,48 @@ class _MessageBubble extends StatelessWidget {
); );
} }
Future<void> _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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isSarMarker = message.isSarMarker; final isSarMarker = message.isSarMarker;