لوحة تحكم الدورة

الحلقة 9: أزرار الأكشن — الاستجابات التفاعلية الفورية

التطبيق "الذكي" حقاً لا يجبر المستخدم دائماً على فتحه. فكر في كيفية سماح تطبيق WhatsApp لك بـ "الرد" أو "وضع علامة مقروء" مباشرة من درج الإشعارات. تسمى هذه الميزة أزرار الأكشن (Action Buttons)، وهي تحول إشعاراتك من تنبيهات سلبية إلى مكونات تفاعلية في نظام تشغيل المستخدم.

سنحترف في هذا الدرس:

  • فئات الإشعارات (Notification Categories): تحديد المخطط الأساسي للأزرار التفاعلية.
  • إنشاء إجراءات مخصصة: إضافة أزرار مثل "مواقق"، "رفض"، أو "تذكير لاحقاً".
  • أزرار الخلفية مقابل أزرار المقدمة: تحديد الإجراءات التي تتطلب فتح التطبيق بالكامل.
  • معالجة الاستجابة: الاستماع لمعرفات أزرار محددة.

1. ما هي فئات الإشعارات؟

قبل أن تتمكن من إظهار الأزرار، يجب أن تخبر نظام التشغيل: "عندما تتلقى إشعاراً من النوع X، أرفق به هذه الأزرار المحددة". تسمى هذه المخططات الفئات (Categories).

لكل فئة معرف فريد (ID) وقائمة من الإجراءات (actions) المرتبطة بها (الأزرار).


2. تعريف الفئات في إكسبو

يجب عليك تعريف فئاتك خلال مرحلة تهيئة التطبيق، تماماً كما فعلنا عند إعداد القنوات والمعالجات.

index.tstypescript
import * as Notifications from 'expo-notifications';

const defineCategories = async () => {
  await Notifications.setNotificationCategoryAsync('task_actions', [
    {
      identifier: 'complete',
      buttonTitle: 'تم الإنجاز ✅',
      options: { opensAppToForeground: false }, // تنفيذ صامت في الخلفية
    },
    {
      identifier: 'remind_later',
      buttonTitle: 'تذكير لاحقاً ⏰',
      options: { opensAppToForeground: true }, // يفتح التطبيق لإعادة الجدولة
    },
  ]);
};

الخيارات:

  • opensAppToForeground: إذا كانت false (خطأ)، فلن يتم مقاطعة تدفق المستخدم الحالي. سيتم تنفيذ المستمع الخاص بك في الخلفية.

3. الاستماع لنقرات الأزرار

لاكتشاف أي زر تم الضغط عليه، نعود إلى addNotificationResponseReceivedListener. ومع ذلك، هذه المرة نتحقق من خاصية actionIdentifier.

index.tstypescript
Notifications.addNotificationResponseReceivedListener(response => {
  const actionId = response.actionIdentifier;
  const { taskId } = response.notification.request.content.data;

  if (actionId === 'complete') {
    // منطق لتحديد المهمة كمكتملة في قاعدة البيانات الخاصة بك
    console.log(`تم تحديد المهمة ${taskId} كمكتملة من درج الإشعارات.`);
  } else if (actionId === 'remind_later') {
    // منطق للانتقال إلى شاشة "إعادة الجدولة"
    navigation.navigate('Reschedule', { id: taskId });
  }
});

4. إطلاق الزناد (Trigger)

لعرض الأزرار، ما عليك سوى إرفاق categoryIdentifier بمحتوى الإشعار الخاص بك عند الجدولة.

index.tstypescript
await Notifications.scheduleNotificationAsync({
  content: {
    title: 'مهمة متبقية 📋',
    body: 'لا تنسَ شراء البقالة اليوم.',
    categoryIdentifier: 'task_actions', // يطابق المعرف أعلاه
    data: { taskId: 101 },
    channelId: 'tasks',
  },
  trigger: null,
});

بمجرد وصول هذا الإشعار، يمكن للمستخدم توسيعه لرؤية زري "تم الإنجاز" و"تذكير لاحقاً".


ملاحظة تقنية: Android مقابل iOS

في نظام Android، تظهر هذه الأزرار مباشرة أسفل نص الإشعار. أما في نظام iOS، فعادة ما يحتاج المستخدم إلى الضغط لفترة طويلة (long-press) على الإشعار للكشف عن أزرار الإجراءات. تأكد من أن تعليمات تجربة المستخدم الخاصة بك تأخذ هذا السلوك الأصلي للمنصة في الاعتبار.


التحدي الخاص بك

قم بإنشاء فئة "دعوة" (Invitation) تحتوي على زري "قبول" و"رفض". أرسل إشعاراً تجريبياً وقم بتنفيذ منطق لإظهار رسالة شكر (alert) إذا تم القبول، أو تسجيل حالة "غير متاح" إذا تم الرفض.