mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-08-10 13:10:44 +02:00
require delete reason, give options
This commit is contained in:
@@ -101,10 +101,17 @@
|
||||
"deleteQueuedForUpload": "Knoten-Löschung zum Upload eingereiht",
|
||||
"confirmDeleteTitle": "Knoten löschen",
|
||||
"confirmDeleteMessage": "Sind Sie sicher, dass Sie Knoten #{} löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"deleteReasonLabel": "Grund für Löschung (Optional)",
|
||||
"deleteReasonHint": "z.B. Gerät entfernt, falsche Position, Duplikat...",
|
||||
"deleteReasonLabel": "Grund für Löschung",
|
||||
"deleteReasonSelectHint": "Auswählen...",
|
||||
"deleteReasonDeviceRemoved": "Gerät entfernt",
|
||||
"deleteReasonDuplicateNode": "Doppelter Knoten",
|
||||
"deleteReasonMisidentifiedInfra": "Falsch identifizierte Infrastruktur",
|
||||
"deleteReasonSpamVandalism": "Spam/Vandalismus",
|
||||
"deleteReasonCustom": "Benutzerdefiniert..",
|
||||
"deleteReasonHint": "Bitte Grund beschreiben...",
|
||||
"mustBeLoggedInToDelete": "Sie müssen mit einem OpenStreetMap-Konto angemeldet sein, um Kartendaten beizutragen."
|
||||
},
|
||||
|
||||
"addNode": {
|
||||
"profile": "Profil",
|
||||
"selectProfile": "Profil auswählen...",
|
||||
|
||||
@@ -138,9 +138,16 @@
|
||||
"deleteQueuedForUpload": "Node deletion queued for upload",
|
||||
"confirmDeleteTitle": "Delete Node",
|
||||
"confirmDeleteMessage": "Are you sure you want to delete node #{}? This action cannot be undone.",
|
||||
"deleteReasonLabel": "Reason for Deletion (Optional)",
|
||||
"deleteReasonHint": "e.g., device removed, incorrect location, duplicate...",
|
||||
"deleteReasonLabel": "Reason for Deletion",
|
||||
"deleteReasonSelectHint": "Select...",
|
||||
"deleteReasonDeviceRemoved": "Device removed",
|
||||
"deleteReasonDuplicateNode": "Duplicate node",
|
||||
"deleteReasonMisidentifiedInfra": "Misidentified infra",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalism",
|
||||
"deleteReasonCustom": "Custom..",
|
||||
"deleteReasonHint": "Please describe the reason...",
|
||||
"mustBeLoggedInToDelete": "You must be logged in with an OpenStreetMap account to contribute map data."
|
||||
|
||||
},
|
||||
"addNode": {
|
||||
"profile": "Profile",
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Eliminación de nodo en cola para subir",
|
||||
"confirmDeleteTitle": "Eliminar Nodo",
|
||||
"confirmDeleteMessage": "¿Estás seguro de que quieres eliminar el nodo #{}? Esta acción no se puede deshacer.",
|
||||
"deleteReasonLabel": "Razón para Eliminación (Opcional)",
|
||||
"deleteReasonHint": "ej. dispositivo removido, ubicación incorrecta, duplicado...",
|
||||
"deleteReasonLabel": "Razón para Eliminación",
|
||||
"deleteReasonSelectHint": "Seleccionar...",
|
||||
"deleteReasonDeviceRemoved": "Dispositivo removido",
|
||||
"deleteReasonDuplicateNode": "Nodo duplicado",
|
||||
"deleteReasonMisidentifiedInfra": "Infraestructura mal identificada",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalismo",
|
||||
"deleteReasonCustom": "Personalizado..",
|
||||
"deleteReasonHint": "Por favor describa la razón...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Debes iniciar sesión con una cuenta de OpenStreetMap para contribuir con datos del mapa."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Suppression de nœud mise en file pour envoi",
|
||||
"confirmDeleteTitle": "Supprimer le Nœud",
|
||||
"confirmDeleteMessage": "Êtes-vous sûr de vouloir supprimer le nœud #{} ? Cette action ne peut pas être annulée.",
|
||||
"deleteReasonLabel": "Raison de Suppression (Optionnel)",
|
||||
"deleteReasonHint": "ex. appareil retiré, emplacement incorrect, doublon...",
|
||||
"deleteReasonLabel": "Raison de Suppression",
|
||||
"deleteReasonSelectHint": "Sélectionner...",
|
||||
"deleteReasonDeviceRemoved": "Appareil retiré",
|
||||
"deleteReasonDuplicateNode": "Nœud dupliqué",
|
||||
"deleteReasonMisidentifiedInfra": "Infrastructure mal identifiée",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalisme",
|
||||
"deleteReasonCustom": "Personnalisé..",
|
||||
"deleteReasonHint": "Veuillez décrire la raison...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Vous devez être connecté avec un compte OpenStreetMap pour contribuer aux données cartographiques."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Eliminazione nodo in coda per il caricamento",
|
||||
"confirmDeleteTitle": "Elimina Nodo",
|
||||
"confirmDeleteMessage": "Sei sicuro di voler eliminare il nodo #{}? Questa azione non può essere annullata.",
|
||||
"deleteReasonLabel": "Motivo per Eliminazione (Opzionale)",
|
||||
"deleteReasonHint": "es. dispositivo rimosso, posizione errata, duplicato...",
|
||||
"deleteReasonLabel": "Motivo per Eliminazione",
|
||||
"deleteReasonSelectHint": "Seleziona...",
|
||||
"deleteReasonDeviceRemoved": "Dispositivo rimosso",
|
||||
"deleteReasonDuplicateNode": "Nodo duplicato",
|
||||
"deleteReasonMisidentifiedInfra": "Infrastruttura identificata erroneamente",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalismo",
|
||||
"deleteReasonCustom": "Personalizzato..",
|
||||
"deleteReasonHint": "Descrivi il motivo...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Devi aver effettuato l'accesso con un account OpenStreetMap per contribuire ai dati della mappa."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Node verwijdering in wachtrij geplaatst voor upload",
|
||||
"confirmDeleteTitle": "Verwijder Node",
|
||||
"confirmDeleteMessage": "Weet u zeker dat u node #{} wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
|
||||
"deleteReasonLabel": "Reden voor Verwijdering (Optioneel)",
|
||||
"deleteReasonHint": "bijv. apparaat verwijderd, onjuiste locatie, duplicaat...",
|
||||
"deleteReasonLabel": "Reden voor Verwijdering",
|
||||
"deleteReasonSelectHint": "Selecteer...",
|
||||
"deleteReasonDeviceRemoved": "Apparaat verwijderd",
|
||||
"deleteReasonDuplicateNode": "Dubbele node",
|
||||
"deleteReasonMisidentifiedInfra": "Verkeerd geïdentificeerde infrastructuur",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalisme",
|
||||
"deleteReasonCustom": "Aangepast..",
|
||||
"deleteReasonHint": "Beschrijf de reden...",
|
||||
|
||||
"mustBeLoggedInToDelete": "U moet ingelogd zijn met een OpenStreetMap-account om kaartgegevens bij te dragen."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Usuwanie węzła umieszczone w kolejce do przesłania",
|
||||
"confirmDeleteTitle": "Usuń Węzeł",
|
||||
"confirmDeleteMessage": "Czy na pewno chcesz usunąć węzeł #{}? Tej akcji nie można cofnąć.",
|
||||
"deleteReasonLabel": "Powód Usunięcia (Opcjonalny)",
|
||||
"deleteReasonHint": "np. urządzenie usunięte, nieprawidłowa lokalizacja, duplikat...",
|
||||
"deleteReasonLabel": "Powód Usunięcia",
|
||||
"deleteReasonSelectHint": "Wybierz...",
|
||||
"deleteReasonDeviceRemoved": "Urządzenie usunięte",
|
||||
"deleteReasonDuplicateNode": "Zduplikowany węzeł",
|
||||
"deleteReasonMisidentifiedInfra": "Błędnie zidentyfikowana infrastruktura",
|
||||
"deleteReasonSpamVandalism": "Spam/wandalizm",
|
||||
"deleteReasonCustom": "Niestandardowy..",
|
||||
"deleteReasonHint": "Opisz powód...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Musisz być zalogowany na konto OpenStreetMap, aby dodawać dane do mapy."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Exclusão de nó na fila para envio",
|
||||
"confirmDeleteTitle": "Excluir Nó",
|
||||
"confirmDeleteMessage": "Tem certeza de que deseja excluir o nó #{}? Esta ação não pode ser desfeita.",
|
||||
"deleteReasonLabel": "Motivo para Exclusão (Opcional)",
|
||||
"deleteReasonHint": "ex. dispositivo removido, localização incorreta, duplicado...",
|
||||
"deleteReasonLabel": "Motivo para Exclusão",
|
||||
"deleteReasonSelectHint": "Selecionar...",
|
||||
"deleteReasonDeviceRemoved": "Dispositivo removido",
|
||||
"deleteReasonDuplicateNode": "Nó duplicado",
|
||||
"deleteReasonMisidentifiedInfra": "Infraestrutura mal identificada",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalismo",
|
||||
"deleteReasonCustom": "Personalizado..",
|
||||
"deleteReasonHint": "Descreva o motivo...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Você precisa estar conectado com uma conta do OpenStreetMap para contribuir com dados do mapa."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Düğüm silme işlemi yükleme için sıraya alındı",
|
||||
"confirmDeleteTitle": "Düğümü Sil",
|
||||
"confirmDeleteMessage": "#{} düğümünü silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.",
|
||||
"deleteReasonLabel": "Silme Nedeni (İsteğe Bağlı)",
|
||||
"deleteReasonHint": "örn. cihaz kaldırıldı, yanlış konum, duplikat...",
|
||||
"deleteReasonLabel": "Silme Nedeni",
|
||||
"deleteReasonSelectHint": "Seçin...",
|
||||
"deleteReasonDeviceRemoved": "Cihaz kaldırıldı",
|
||||
"deleteReasonDuplicateNode": "Yinelenen düğüm",
|
||||
"deleteReasonMisidentifiedInfra": "Yanlış tanımlanmış altyapı",
|
||||
"deleteReasonSpamVandalism": "Spam/vandalizm",
|
||||
"deleteReasonCustom": "Özel..",
|
||||
"deleteReasonHint": "Lütfen nedeni açıklayın...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Harita verilerine katkıda bulunmak için bir OpenStreetMap hesabıyla oturum açmış olmanız gerekir."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "Видалення вузла поставлено в чергу для завантаження",
|
||||
"confirmDeleteTitle": "Видалити Вузол",
|
||||
"confirmDeleteMessage": "Ви впевнені, що хочете видалити вузол #{}? Цю дію не можна скасувати.",
|
||||
"deleteReasonLabel": "Причина Видалення (Опціонально)",
|
||||
"deleteReasonHint": "наприклад пристрій видалено, неправильне розташування, дублікат...",
|
||||
"deleteReasonLabel": "Причина Видалення",
|
||||
"deleteReasonSelectHint": "Вибрати...",
|
||||
"deleteReasonDeviceRemoved": "Пристрій видалено",
|
||||
"deleteReasonDuplicateNode": "Дубльований вузол",
|
||||
"deleteReasonMisidentifiedInfra": "Неправильно ідентифікована інфраструктура",
|
||||
"deleteReasonSpamVandalism": "Спам/вандалізм",
|
||||
"deleteReasonCustom": "Власний..",
|
||||
"deleteReasonHint": "Опишіть причину...",
|
||||
|
||||
"mustBeLoggedInToDelete": "Ви повинні увійти в обліковий запис OpenStreetMap, щоб надавати дані карти."
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -138,8 +138,15 @@
|
||||
"deleteQueuedForUpload": "节点删除已排队上传",
|
||||
"confirmDeleteTitle": "删除节点",
|
||||
"confirmDeleteMessage": "您确定要删除节点 #{} 吗?此操作无法撤销。",
|
||||
"deleteReasonLabel": "删除原因(可选)",
|
||||
"deleteReasonHint": "例如:设备已移除、位置错误、重复...",
|
||||
"deleteReasonLabel": "删除原因",
|
||||
"deleteReasonSelectHint": "请选择...",
|
||||
"deleteReasonDeviceRemoved": "设备已移除",
|
||||
"deleteReasonDuplicateNode": "重复节点",
|
||||
"deleteReasonMisidentifiedInfra": "识别错误的基础设施",
|
||||
"deleteReasonSpamVandalism": "垃圾信息/破坏",
|
||||
"deleteReasonCustom": "自定义..",
|
||||
"deleteReasonHint": "请描述原因...",
|
||||
|
||||
"mustBeLoggedInToDelete": "您必须使用 OpenStreetMap 账户登录才能贡献地图数据。"
|
||||
},
|
||||
"addNode": {
|
||||
|
||||
@@ -274,6 +274,48 @@ class NodeTagSheet extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
enum _DeleteReason {
|
||||
deviceRemoved,
|
||||
duplicateNode,
|
||||
misidentifiedInfra,
|
||||
spamVandalism,
|
||||
custom,
|
||||
}
|
||||
|
||||
extension _DeleteReasonLabel on _DeleteReason {
|
||||
String label(LocalizationService locService) {
|
||||
switch (this) {
|
||||
case _DeleteReason.deviceRemoved:
|
||||
return locService.t('node.deleteReasonDeviceRemoved');
|
||||
case _DeleteReason.duplicateNode:
|
||||
return locService.t('node.deleteReasonDuplicateNode');
|
||||
case _DeleteReason.misidentifiedInfra:
|
||||
return locService.t('node.deleteReasonMisidentifiedInfra');
|
||||
case _DeleteReason.spamVandalism:
|
||||
return locService.t('node.deleteReasonSpamVandalism');
|
||||
case _DeleteReason.custom:
|
||||
return locService.t('node.deleteReasonCustom');
|
||||
}
|
||||
}
|
||||
|
||||
/// The text used to build the changeset comment (kept in English/consistent
|
||||
/// regardless of UI language, matching prior app behavior for uploads).
|
||||
String get commentText {
|
||||
switch (this) {
|
||||
case _DeleteReason.deviceRemoved:
|
||||
return 'device removed';
|
||||
case _DeleteReason.duplicateNode:
|
||||
return 'duplicate node';
|
||||
case _DeleteReason.misidentifiedInfra:
|
||||
return 'misidentified infra';
|
||||
case _DeleteReason.spamVandalism:
|
||||
return 'spam/vandalism';
|
||||
case _DeleteReason.custom:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _DeleteNodeDialog extends StatefulWidget {
|
||||
final String nodeId;
|
||||
final LocalizationService locService;
|
||||
@@ -289,6 +331,7 @@ class _DeleteNodeDialog extends StatefulWidget {
|
||||
|
||||
class _DeleteNodeDialogState extends State<_DeleteNodeDialog> {
|
||||
late final TextEditingController _commentController;
|
||||
_DeleteReason? _selectedReason;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -302,6 +345,14 @@ class _DeleteNodeDialogState extends State<_DeleteNodeDialog> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get _canConfirm {
|
||||
if (_selectedReason == null) return false;
|
||||
if (_selectedReason == _DeleteReason.custom) {
|
||||
return _commentController.text.trim().isNotEmpty;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
@@ -317,16 +368,39 @@ class _DeleteNodeDialogState extends State<_DeleteNodeDialog> {
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _commentController,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.locService.t('node.deleteReasonHint'),
|
||||
border: const OutlineInputBorder(),
|
||||
DropdownButtonFormField<_DeleteReason>(
|
||||
initialValue: _selectedReason,
|
||||
hint: Text(widget.locService.t('node.deleteReasonSelectHint')),
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
maxLines: 2,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
items: _DeleteReason.values
|
||||
.map((reason) => DropdownMenuItem(
|
||||
value: reason,
|
||||
child: Text(reason.label(widget.locService)),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (reason) {
|
||||
setState(() {
|
||||
_selectedReason = reason;
|
||||
});
|
||||
},
|
||||
),
|
||||
if (_selectedReason == _DeleteReason.custom) ...[
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _commentController,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.locService.t('node.deleteReasonHint'),
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
maxLines: 2,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
onChanged: (_) => setState(() {}),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
@@ -335,17 +409,22 @@ class _DeleteNodeDialogState extends State<_DeleteNodeDialog> {
|
||||
child: Text(widget.locService.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final comment = _commentController.text.trim();
|
||||
final finalComment = comment.isEmpty
|
||||
? 'Delete a surveillance node'
|
||||
: 'Delete a surveillance node: $comment';
|
||||
Navigator.of(context).pop((confirmed: true, comment: finalComment));
|
||||
},
|
||||
onPressed: _canConfirm
|
||||
? () {
|
||||
final reasonText = _selectedReason == _DeleteReason.custom
|
||||
? _commentController.text.trim()
|
||||
: _selectedReason!.commentText;
|
||||
final finalComment = reasonText.isEmpty
|
||||
? 'Delete a surveillance node'
|
||||
: 'Delete a surveillance node: $reasonText';
|
||||
Navigator.of(context).pop((confirmed: true, comment: finalComment));
|
||||
}
|
||||
: null,
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
child: Text(widget.locService.t('actions.delete')),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user