mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
feat(apple): local notifications for transfer lifecycle events
Adds background notifications for the "the thing you were waiting for is
done" moments, alongside the existing incoming-approval-request one:
- a receive finished downloading (receive -> done)
- a receive failed / was interrupted (receive -> failed)
- a share you own failed (send -> failed)
- a receiver finished downloading your share (receiver status completed)
A new TransferNotificationCoordinator observes core state + signals and
publishes these; the decision of which moments notify is a pure function
(plannedTransferNotifications / plannedReceiverNotifications), unit-tested
independently. The first state snapshot only primes existing history as seen
so launch doesn't spam.
Notification permission is now the single source of truth. The in-app
notifications toggle and its decoupled UserDefaults preference are gone;
the Settings section shows an "Allow notifications" button that requests the
OS permission (or deep-links to Settings once decided), and notifications
gate purely on `permission == .granted`.
macOS delivery fixes:
- add a UNUserNotificationCenterDelegate so banners present even while the
app is active (the app window is usually open on macOS)
- present-when-active on macOS, suppress-when-foregrounded on iOS
- reserve the notification id before awaiting publish: the CombineLatest
fired several times and re-added the same identifier, which macOS
coalesces into a silent update with no banner
- LocalNotificationService seeds its permission at init so gating can't
race a not-yet-refreshed .notDetermined
Eight localized title/body strings added (apple-only); the shared
notifications_description copy is generalized from "receive requests" to
"transfer activity".
This commit is contained in:
@@ -1757,15 +1757,15 @@
|
||||
"notifications_description": {
|
||||
"context": "Settings > Notifications: explanation of what notifications are used for.",
|
||||
"translations": {
|
||||
"en": "Get notified about new receive requests while VniDrop is in the background.",
|
||||
"fr": "Soyez averti des nouvelles demandes de réception lorsque VniDrop est en arrière-plan.",
|
||||
"es": "Reciba avisos sobre nuevas solicitudes de recepción cuando VniDrop está en segundo plano.",
|
||||
"it": "Ricevi avvisi sulle nuove richieste di ricezione quando VniDrop è in background.",
|
||||
"de": "Werden Sie über neue Empfangsanfragen benachrichtigt, während VniDrop im Hintergrund läuft.",
|
||||
"pt": "Seja notificado sobre novos pedidos de receção enquanto o VniDrop está em segundo plano.",
|
||||
"pl": "Otrzymuj powiadomienia o nowych prośbach o odbiór, gdy VniDrop działa w tle.",
|
||||
"nl": "Ontvang meldingen over nieuwe ontvangstverzoeken terwijl VniDrop op de achtergrond draait.",
|
||||
"ru": "Получайте уведомления о новых запросах на получение, пока VniDrop работает в фоне."
|
||||
"en": "Get notified about transfer activity while VniDrop is in the background.",
|
||||
"fr": "Soyez averti de l’activité des transferts lorsque VniDrop est en arrière-plan.",
|
||||
"es": "Reciba avisos sobre la actividad de las transferencias cuando VniDrop está en segundo plano.",
|
||||
"it": "Ricevi avvisi sull’attività dei trasferimenti quando VniDrop è in background.",
|
||||
"de": "Werden Sie über Übertragungsaktivitäten benachrichtigt, während VniDrop im Hintergrund läuft.",
|
||||
"pt": "Seja notificado sobre a atividade das transferências enquanto o VniDrop está em segundo plano.",
|
||||
"pl": "Otrzymuj powiadomienia o aktywności transferów, gdy VniDrop działa w tle.",
|
||||
"nl": "Ontvang meldingen over overdrachtsactiviteit terwijl VniDrop op de achtergrond draait.",
|
||||
"ru": "Получайте уведомления об активности передач, пока VniDrop работает в фоне."
|
||||
}
|
||||
},
|
||||
"notifications_enabled_message": {
|
||||
@@ -1810,6 +1810,170 @@
|
||||
"ru": "Уведомления отключены для VniDrop. Вы можете включить их в Настройках."
|
||||
}
|
||||
},
|
||||
"notifications_receive_completed_body": {
|
||||
"context": "Notification body shown when an incoming transfer finishes downloading. {transferName} = transfer name.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "transferName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"translations": {
|
||||
"en": "“{transferName}” finished downloading.",
|
||||
"fr": "« {transferName} » a fini de se télécharger.",
|
||||
"es": "«{transferName}» terminó de descargarse.",
|
||||
"it": "«{transferName}» è stato scaricato.",
|
||||
"de": "„{transferName}“ wurde vollständig heruntergeladen.",
|
||||
"pt": "«{transferName}» concluiu a transferência.",
|
||||
"pl": "Zakończono pobieranie „{transferName}”.",
|
||||
"nl": "‘{transferName}’ is volledig gedownload.",
|
||||
"ru": "«{transferName}» завершил загрузку."
|
||||
}
|
||||
},
|
||||
"notifications_receive_completed_title": {
|
||||
"context": "Notification title shown when an incoming transfer finishes downloading.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"translations": {
|
||||
"en": "Download complete",
|
||||
"fr": "Téléchargement terminé",
|
||||
"es": "Descarga completada",
|
||||
"it": "Download completato",
|
||||
"de": "Download abgeschlossen",
|
||||
"pt": "Transferência concluída",
|
||||
"pl": "Pobieranie zakończone",
|
||||
"nl": "Download voltooid",
|
||||
"ru": "Загрузка завершена"
|
||||
}
|
||||
},
|
||||
"notifications_receive_failed_body": {
|
||||
"context": "Notification body shown when an incoming transfer fails. {transferName} = transfer name.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "transferName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"translations": {
|
||||
"en": "“{transferName}” couldn’t be received.",
|
||||
"fr": "« {transferName} » n’a pas pu être reçu.",
|
||||
"es": "No se pudo recibir «{transferName}».",
|
||||
"it": "Impossibile ricevere «{transferName}».",
|
||||
"de": "„{transferName}“ konnte nicht empfangen werden.",
|
||||
"pt": "Não foi possível receber «{transferName}».",
|
||||
"pl": "Nie udało się odebrać „{transferName}”.",
|
||||
"nl": "‘{transferName}’ kon niet worden ontvangen.",
|
||||
"ru": "Не удалось получить «{transferName}»."
|
||||
}
|
||||
},
|
||||
"notifications_receive_failed_title": {
|
||||
"context": "Notification title shown when an incoming transfer fails.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"translations": {
|
||||
"en": "Download failed",
|
||||
"fr": "Échec du téléchargement",
|
||||
"es": "Error en la descarga",
|
||||
"it": "Download non riuscito",
|
||||
"de": "Download fehlgeschlagen",
|
||||
"pt": "Falha na transferência",
|
||||
"pl": "Pobieranie nie powiodło się",
|
||||
"nl": "Download mislukt",
|
||||
"ru": "Ошибка загрузки"
|
||||
}
|
||||
},
|
||||
"notifications_receiver_completed_body": {
|
||||
"context": "Notification body shown to the sender when a receiver finishes downloading a shared transfer. {receiver} = receiver name, {transferName} = transfer name.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "receiver",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "transferName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"translations": {
|
||||
"en": "{receiver} finished receiving “{transferName}”.",
|
||||
"fr": "{receiver} a fini de recevoir « {transferName} ».",
|
||||
"es": "{receiver} terminó de recibir «{transferName}».",
|
||||
"it": "{receiver} ha finito di ricevere «{transferName}».",
|
||||
"de": "{receiver} hat „{transferName}“ vollständig empfangen.",
|
||||
"pt": "{receiver} terminou de receber «{transferName}».",
|
||||
"pl": "{receiver} zakończył odbieranie „{transferName}”.",
|
||||
"nl": "{receiver} heeft ‘{transferName}’ volledig ontvangen.",
|
||||
"ru": "{receiver} завершил получение «{transferName}»."
|
||||
}
|
||||
},
|
||||
"notifications_receiver_completed_title": {
|
||||
"context": "Notification title shown to the sender when a receiver finishes downloading a shared transfer.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"translations": {
|
||||
"en": "Transfer received",
|
||||
"fr": "Transfert reçu",
|
||||
"es": "Transferencia recibida",
|
||||
"it": "Trasferimento ricevuto",
|
||||
"de": "Übertragung empfangen",
|
||||
"pt": "Transferência recebida",
|
||||
"pl": "Transfer odebrany",
|
||||
"nl": "Overdracht ontvangen",
|
||||
"ru": "Передача получена"
|
||||
}
|
||||
},
|
||||
"notifications_send_failed_body": {
|
||||
"context": "Notification body shown to the sender when a shared transfer fails. {transferName} = transfer name.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "transferName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"translations": {
|
||||
"en": "“{transferName}” couldn’t be shared.",
|
||||
"fr": "« {transferName} » n’a pas pu être partagé.",
|
||||
"es": "No se pudo compartir «{transferName}».",
|
||||
"it": "Impossibile condividere «{transferName}».",
|
||||
"de": "„{transferName}“ konnte nicht geteilt werden.",
|
||||
"pt": "Não foi possível partilhar «{transferName}».",
|
||||
"pl": "Nie udało się udostępnić „{transferName}”.",
|
||||
"nl": "‘{transferName}’ kon niet worden gedeeld.",
|
||||
"ru": "Не удалось поделиться «{transferName}»."
|
||||
}
|
||||
},
|
||||
"notifications_send_failed_title": {
|
||||
"context": "Notification title shown to the sender when a shared transfer fails.",
|
||||
"targets": [
|
||||
"apple"
|
||||
],
|
||||
"translations": {
|
||||
"en": "Sharing failed",
|
||||
"fr": "Échec du partage",
|
||||
"es": "Error al compartir",
|
||||
"it": "Condivisione non riuscita",
|
||||
"de": "Freigabe fehlgeschlagen",
|
||||
"pt": "Falha na partilha",
|
||||
"pl": "Udostępnianie nie powiodło się",
|
||||
"nl": "Delen mislukt",
|
||||
"ru": "Не удалось поделиться"
|
||||
}
|
||||
},
|
||||
"notifications_settings_open_failed": {
|
||||
"context": "Settings > Notifications: error when the OS notification settings can't be opened.",
|
||||
"translations": {
|
||||
|
||||
Reference in New Issue
Block a user