Notification rate limiting (#110)

* Add notification rate limiting with privacy-safe debug logging

- Add batching system to prevent notification storms (3s rate limit, 5s batch window)
- Queue rapid notifications and show batch summaries
- Debug logs show device names for adverts, sender/channel for messages (no content leaks)
- Remove unused _maxBatchSize constant

Context: Added after getting notification-flooded while evaluating RF flood management. The irony.

* Update notification_service.dart

I made a mistake and removed this

* Add l10n support for notification strings

Addresses PR #110 review feedback to use the translations system:
- Add notification strings to app_en.arb (plurals for batch summary)
- Update NotificationService to use lookupAppLocalizations()
- Wire locale from MaterialApp to NotificationService
- Regenerate localization files

New strings added (English only, translations needed):
- notification_activityTitle: "MeshCore Activity"
- notification_messagesCount: "{count} message(s)"
- notification_channelMessagesCount: "{count} channel message(s)"
- notification_newNodesCount: "{count} new node(s)"
- notification_newTypeDiscovered: "New {type} discovered"
- notification_receivedNewMessage: "Received new message"

* Add notification string translations for all supported languages

Translated notification_activityTitle, notification_messagesCount,
notification_channelMessagesCount, notification_newNodesCount,
notification_newTypeDiscovered, and notification_receivedNewMessage
to: bg, de, es, fr, it, nl, pl, pt, ru, sk, sl, sv, uk, zh

Includes proper ICU plural forms for Slavic languages (few/many/other)
and Slovenian dual form.

* Apply dart format to notification_service.dart

---------

Co-authored-by: Winston Lowe <wel97459@gmail.com>
This commit is contained in:
Ryan Malloy
2026-02-08 19:42:15 -07:00
committed by GitHub
parent ea43cf17eb
commit daca42701c
34 changed files with 1282 additions and 7 deletions
+28 -1
View File
@@ -1346,12 +1346,39 @@
"contacts_contactAdvertCopied": "Advert copied to Clipboard.",
"contacts_contactAdvertCopyFailed": "Copying advert to Clipboard failed.",
"notification_activityTitle": "MeshCore Activity",
"notification_messagesCount": "{count} {count, plural, =1{message} other{messages}}",
"@notification_messagesCount": {
"placeholders": {
"count": {"type": "int"}
}
},
"notification_channelMessagesCount": "{count} {count, plural, =1{channel message} other{channel messages}}",
"@notification_channelMessagesCount": {
"placeholders": {
"count": {"type": "int"}
}
},
"notification_newNodesCount": "{count} {count, plural, =1{new node} other{new nodes}}",
"@notification_newNodesCount": {
"placeholders": {
"count": {"type": "int"}
}
},
"notification_newTypeDiscovered": "New {contactType} discovered",
"@notification_newTypeDiscovered": {
"placeholders": {
"contactType": {"type": "String"}
}
},
"notification_receivedNewMessage": "Received new message",
"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_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",