Привет ![]()
Мы столкнулись с необычным поведением (возможно, это баг…) при настройке push-уведомлений в iOS PWA. Интерфейс ведёт себя так, будто подписка на push-уведомления уже настроена, но на самом деле ничего не произошло, и пользователь никогда не получит push-уведомление.
(tl;dr: я, кажется, знаю, как это исправить, и могу предоставить PR)
Шаги для воспроизведения 
Проблема заключается в включении push-уведомлений сразу после установки PWA на iOS.
- Откройте ваш экземпляр Discourse в мобильном Safari на iOS.
- Откройте меню «Поделиться» и выберите «Добавить на главный экран».
- Откройте новый PWA с главного экрана.
- Вы увидите баннер с вопросом, хотите ли вы включить push-уведомления.
- Нажмите на ссылку «Включить уведомления».
- Появится системное диалоговое окно: «xyz» хочет отправлять вам уведомления — примите это.
- Перейдите в настройки уведомлений: вы увидите, что
live notificationsне включены.- При проверке на сервере вы также не найдёте новой записи
PushSubscriptionдля этого пользователя.
- При проверке на сервере вы также не найдёте новой записи
Ожидаемое поведение 
После шага 5 вы уже должны получить push-уведомление о том, что уведомления включены. В базе данных также должна появиться новая запись PushSubscription для текущего пользователя, а его настройка получения live notifications в PWA должна быть включена.
Проблема 
В только что запущенном PWA сервис-воркер установлен и активирован, но ещё не контролирует страницу. Из-за этого проверка в lib/push-notifications.js, функция isPushNotificationsSupported(), всё ещё возвращает false, поскольку navigator.serviceWorker.controller возвращает null. Вот эти две важные строки:
navigator.serviceWorker.controller &&
navigator.serviceWorker.controller.state === "activated"
В результате интерфейс сообщает пользователю, что всё в порядке, но он никогда не получит push-уведомление.
При первой загрузке PWA не контролируется, и вызов subscribe() никогда не выполняется, даже несмотря на то, что пользователь дал разрешение… ![]()
Пользователи могут исправить проблему самостоятельно, если знают как:
- Полностью закрыть PWA (смахнуть его…).
- Снова открыть PWA.
- Перейти в настройки уведомлений.
- Снова включить
live notifications. - → На этот раз должна появиться новая запись
PushSubscription, и уведомления будут настроены.
Возможное исправление 
Я обошёл эту проблему, зарегистрировав дополнительный сервис-воркер, который вызывает skipWaiting() и clients.claim() при установке/активации. Благодаря этому он сразу берёт контроль над PWA, подписка выполняется, и создаётся соответствующая запись PushSubscription.
Я развернул это как «горячее исправление» в рамках одного из своих кастомных плагинов, чтобы исправить ситуацию для моих пользователей, не углубляясь в форк ядра Discourse…
Это всего лишь два изменения:
# plugin.rb
register_service_worker "push-notification-setup.js"
// assets/push-notification-setup.js
self.addEventListener("install", function () {
self.skipWaiting();
});
self.addEventListener("activate", function (event) {
event.waitUntil(self.clients.claim());
});
Однако я считаю, что это исправление должно быть включено в ядро Discourse. В текущем виде плагин берёт на себя излишний контроль над PWA. Я могу предоставить PR, который скорректирует проверки в ядре Discourse так, чтобы подписка работала корректно. Буду рад обсудить это здесь, но не стесняйтесь высказать своё мнение по этой теме.