اشتراك الإشعارات في PWA على iOS يفشل بصمت بسبب عدم سيطرة SW على التطبيق

مرحبًا :waving_hand:

واجهنا سلوكًا غريبًا (أو ربما خطأ…) عند إعداد إشعارات الدفع في تطبيق الويب التقدمي (PWA) لنظام iOS. يبدو أن الواجهة قد تم إعداد اشتراك إشعارات الدفع بنجاح، بينما في الخلفية لم يحدث شيء بعد، ولن يتلقى المستخدم أي إشعار دفع على الإطلاق.

(ملخص سريع: أعتقد أنني أعرف كيفية إصلاحه ويمكنني تقديم طلب سحب (PR))

خطوات التكرار :footprints:

المشكلة تتعلق بتمكين إشعارات الدفع مباشرة بعد تثبيت تطبيق الويب التقدمي (PWA) على iOS.

  1. افتح مثيل Discourse الخاص بك في متصفح Safari المحمول على iOS.
  2. افتح قائمة المشاركة واختر “إضافة إلى الشاشة الرئيسية”.
  3. افتح تطبيق الويب التقدمي (PWA) الجديد من شاشتك الرئيسية.
  4. ستظهر لك لافتة تسألك عما إذا كنت تريد تمكين إشعارات الدفع.
  5. انقر على رابط “تمكين الإشعارات”.
    1. ستظهر نافذة نظام تقول: "xyz" ترغب في إرسال إشعارات إليك - وافق عليها.
  6. عند الانتقال إلى تفضيلات الإشعارات الخاصة بك، ستلاحظ أن الإشعارات المباشرة غير مفعلة.
    1. عند التحقق من الخادم، لن تجد أيضًا سجل PushSubscription جديد للمستخدم.

السلوك المتوقع :books:

بعد الخطوة 5، كان يجب أن تتلقى إشعار دفع يفيد بأن الإشعارات مفعلة. كما يجب أن يكون هناك سجل PushSubscription جديد للمستخدم الحالي في قاعدة البيانات، ويجب أن تكون إعداداته لاستقبال الإشعارات المباشرة في تطبيق الويب التقدمي (PWA) مفعلة.

المشكلة :bug:

في تطبيق ويب تقدمي (PWA) تم تشغيله حديثًا، تكون خدمة العامل (service worker) قد تم تثبيتها وتفعيلها، لكنها لا تتحكم في الصفحة بعد. نتيجة لذلك، ستظل الدالة isPushNotificationsSupported() في lib/push-notifications.js ترجع قيمة false، لأن navigator.serviceWorker.controller ترجع null. هذان السطران هما الأهم:

navigator.serviceWorker.controller &&
navigator.serviceWorker.controller.state === "activated"

نتيجة لذلك، تقترح الواجهة للمستخدم أن كل شيء على ما يرام في إعداداته، لكنه لن يتلقى أي إشعار دفع على الإطلاق.

في التحميل الأول، يكون تطبيق الويب التقدمي (PWA) غير خاضع للتحكم، ولا يتم استدعاء subscribe() أبدًا، على الرغم من أن المستخدم منح الإذن… :bug:

يمكن للمستخدمين إصلاح المشكلة بأنفسهم إذا عرفوا كيفية ذلك:

  1. أغلق تطبيق الويب التقدمي (PWA) تمامًا (اسحبه بعيدًا…).
  2. افتح تطبيق الويب التقدمي (PWA) مرة أخرى.
  3. انتقل إلى تفضيلات الإشعارات الخاصة بك.
  4. قم بتمكين الإشعارات المباشرة مرة أخرى.
  5. → هذه المرة، يجب أن يكون هناك سجل PushSubscription جديد ويتم إعداد الإشعارات بنجاح.

الإصلاح المحتمل :adhesive_bandage:

تجاوزت هذه المشكلة عن طريق تسجيل خدمة عامل أخرى تستدعي 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 بشكل مناسب بحيث يعمل الاشتراك فعليًا. سأكون سعيدًا بسماع آرائكم حول هذا الموضوع هنا، ولكن لا تترددوا في التعبير عن آرائكم في أي وقت.

إعجاب واحد (1)

هذا هو طلب الدمج (PR) الذي يحتوي على إصلاح للنواة الأساسية لـ Discourse → FIX: Allow push notification subscriptions on first launch of iOS PWA · Pull Request #39885 · discourse/discourse

يُصلح هذا الطلب المشكلة الموصوفة هنا، حيث فشلت الاشتراكات صامتًا ولم تصل إلى الخادم. لكن ما يزال ناقصًا، لضمان الأمان التام، هو أن إشعار الدفع الأول المستلم لن يكون قابلاً للتوجيه داخل التطبيق دون أن يتحكم فيه عامل الخدمة (Service Worker)، مما يعني ضرورة إعادة تشغيل التطبيق من قبل المستخدم.

يمكنني إضافة هذا أيضًا فوق طلب الدمج الخاص بي. لكنني لست متأكدًا بنسبة 100% مما إذا كان الإصلاح هو المطلوب.

إعجاب واحد (1)