تطبيقات الويب التقدّمية: تعزيز تطبيق الويب التقدّمي

1. مرحبًا

في هذا التمرين العملي، ستأخذ تطبيق ويب حاليًا وتضيف إليه إمكانات متقدّمة. هذا هو السادس في سلسلة من دروس الترميز التطبيقية المصاحبة لورشة عمل تطبيقات الويب التقدّمية. كانت ورشة الترميز السابقة بعنوان عرض طلبات التثبيت وقياسها. يتضمّن هذا المسار التدريبي العملي سلسلتَين إضافيتَين من دروس البرمجة.

أهداف الدورة التعليمية

  • فتح الملفات وحفظها من نظام ملفات المستخدم باستخدام File System Access API
  • تسجيل تطبيق الويب التقدّمي (PWA) المثبَّت كمعالج ملفات باستخدام File Handling API
  • اختيار الشاشة المناسبة لفتح نافذة باستخدام واجهة برمجة التطبيقات Multi-Screen Window Placement API
  • منع الشاشة من الانتقال إلى وضع السكون باستخدام Screen Wake Lock API

ما يتعين عليك معرفته

  • JavaScript

المتطلبات

  • متصفّح متوافق مع واجهات برمجة التطبيقات المذكورة أعلاه بالنسبة إلى بعض واجهات برمجة التطبيقات، قد تحتاج إلى استخدام متصفّح يتضمّن إصدارًا تجريبيًا نشطًا من المطوّرين أو إصدارًا تجريبيًا من المصدر لإكمال العملية.

2. إكمال الإعداد

ابدأ إما باستنساخ الرمز الأولي أو تنزيله لإكمال هذا الدرس التطبيقي حول الترميز:

إذا نسخت المستودع، تأكَّد من أنّك تستخدم الفرع pwa05--empowering-your-pwa. يحتوي ملف ZIP أيضًا على الرمز الخاص بهذا الفرع.

يتطلّب هذا الرمز الأساسي الإصدار 14 من Node.js أو إصدارًا أحدث. بعد توفّر الرمز، شغِّل npm ci من سطر الأوامر في مجلد الرمز لتثبيت جميع الملفات التابعة التي ستحتاج إليها. بعد ذلك، شغِّل npm start لبدء خادم التطوير الخاص بتجربة البرمجة.

يقدّم ملف README.md لرمز المصدر شرحًا لجميع الملفات الموزّعة. بالإضافة إلى ذلك، إليك الملفات الرئيسية الحالية التي ستعمل عليها خلال هذا الدرس العملي:

الملفات الرئيسية

  • js/lib/actions.js: توفّر فئة أساسية للقائمة

ملاحظة مهمة بشأن البنية

خلال هذا الدرس التطبيقي حول الترميز، ستعدّل js/lib/action.js الذي يدير الإجراءات لمختلف الأزرار في قائمة التطبيق. يمكنك الوصول إلى أي موقع في أداة إنشاء القائمة التي تمّت تهيئتها، والتي ستتضمّن this.editor لمثيل محرّر النصوص الرئيسي. في ما يلي طريقتان مهمّتان للمحرّر ستستخدمهما خلال هذا الدرس العملي:

  • this.editor.setContent(content): يضبط محتوى المحرّر على وسيطة المحتوى المقدَّمة
  • this.editor.content() - للحصول على المحتوى الحالي للمحرّر

3- إدارة الملفات

أصبح بإمكانك الآن فتح الملفات وحفظها وإنشاء ملفات جديدة على جهاز كمبيوتر المستخدم بفضل واجهة برمجة التطبيقات File System Access API. بالإضافة إلى File Handling API التي تتيح للمستخدمين فتح الملفات مباشرةً في تطبيق الويب التقدّمي، يمكن أن يبدو تطبيق الويب التقدّمي مدمجًا بسلاسة في حياة المستخدمين اليومية.

الفتح من داخل التطبيق

أول إجراء يجب ربطه هو إمكانية فتح ملف من نظام ملفات المستخدم من داخل التطبيق. في js/lib/actions.js، ضمن طريقة open لفئة Actions، اكتب الرمز البرمجي الذي ينفّذ ما يلي:

  • افتح أداة اختيار الملفات التي ستأخذ ملف text/markdown بالامتدادات .md أو .markdown
  • اضبط عنوان الصفحة على اسم الملفات المفتوحة، بالإضافة إلى PWA Edit
  • تخزين معالج الملف ضمن this.handler
  • ضبط محتوى المحرِّر على محتوى النص في الملف
  • احفظ المعالج في مستودع العناصر settings في قاعدة بيانات IndexedDB settings-store.

إيجابي : تذكَّر أنّ منشئات الفئات لا يمكن أن تكون دوال async، ولكن يمكنك استدعاء الوعود بداخلها.

بعد أن أصبح بإمكانك فتح ملف وحفظ الملف المفتوح بين عمليات التحميل، هناك أمران آخران عليك تنفيذهما: إعادة إعداد المعالج عند تحميل التطبيق، وإلغاء إعداده عندما يعيد المستخدم ضبط التطبيق.

لتحقيق الهدف الأول، في الدالة الإنشائية للفئة Actions في js/lib/actions.js، اتّبِع الخطوات التالية:

  • فتح قاعدة بيانات settings-store
  • الحصول على المعالج المحفوظ من مساحة تخزين العناصر settings
  • اضبط قيمة this.handler على القيمة التي تم استردادها وعنوان الصفحة على اسم ملف المعالج (بالإضافة إلى PWA Edit) إذا كان هناك معالج محفوظ.

لإعادة ضبط حالة التطبيق (التي يمكن إجراؤها باستخدام CTRL/CMD+Shift+R)، عدِّل طريقة reset للفئة Actions في js/lib/actions.js لتنفيذ ما يلي:

  • ضبط عنوان المستند على PWA Edit
  • ضبط محتوى المحرِّر على سلسلة فارغة
  • اضبط قيمة this.handler على null.
  • احذف المعالج المحفوظ من متجر العناصر settings

الفتح من نظام ملفات المستخدم

بعد أن أصبح بإمكانك فتح ملف من تطبيقك، عليك السماح للمستخدمين بفتح تطبيقك باستخدام ملفاتهم. سيسمح التسجيل كمعالج ملفات لجهاز للمستخدم بفتح الملفات في تطبيقك من أي مكان في نظام الملفات.

النتيجة السلبية : قد تحتاج إلى تفعيل تجربة مطوّرين أو تجربة أصلية لكي تعمل هذه الميزة. إذا كنت بحاجة إلى تفعيل "تجربة المطوّرين"، ننصحك بتفعيلها في نسخة من Chrome Canary بدلاً من متصفّحك العادي. إذا كنت بحاجة إلى تفعيل تجربة Origin، عليك التسجيل فيها كالمعتاد وإضافة العلامة إلى index.html.

للبدء، أضِف في manifest.json إدخال file_handlers ينفّذ ما يلي:

  • يفتح عند الساعة /
  • يقبل text/markdown مع امتدادات الملفات .md أو .markdown.

سيسمح ذلك للمستخدمين بفتح الملفات باستخدام تطبيقك، ولكن لن يتم فتح الملفات في تطبيقك فعليًا. ولإجراء ذلك، اتّبِع الخطوات التالية في الفئة Actions في js/lib/actions.js:

  • أضِف window.launchQueue مستهلكًا في الدالة الإنشائية، واستدعِ this.open باستخدام المعالج، إذا كان هناك أي معالج.
  • تعديل this.open لقبول معالج تشغيل اختياري
    • إذا كان هذا المتغير موجودًا وكان مثيلاً من FileSystemFileHandle، استخدِمه كمعالج ملف للدالة
    • إذا لم يكن كذلك، افتح أداة اختيار الملفات

بعد تنفيذ الخطوتين أعلاه، ثبِّت تطبيق الويب التقدّمي وحاوِل فتح ملف باستخدامه من نظام الملفات.

حفظ ملف

هناك مساران مختلفان للحفظ قد يريد المستخدم اتّباعهما: حفظ التغييرات في ملف مفتوح حاليًا، أو الحفظ في ملف جديد. باستخدام File System Access API، يعني الحفظ في ملف جديد إنشاء ملف جديد والحصول على معالج ملف، لذا لنبدأ بالحفظ من معالج حالي.

في طريقة save في فئة Actions في js/lib/actions.js، اتّبِع الخطوات التالية:

  • الحصول على المعالج إما من this.handler أو، إذا لم يكن ذلك متاحًا، الحصول على المعالج المحفوظ من قاعدة البيانات
  • إنشاء FileSystemWritableFileStream لمعالج الملفات
  • كتابة محتوى المحرّر في البث
  • إغلاق البث

بعد أن تتمكّن من حفظ ملف، حان الوقت لتنفيذ عملية الحفظ باسم. لإجراء ذلك، اتّبِع الخطوات التالية في طريقة saveAs في فئة Actions في js/lib/actions.js:

  • عرض أداة اختيار ملف الحفظ، مع وصفها بأنّها Markdown File والسماح لها بقبول ملفات text/markdown بالامتداد .md
  • ضبط this.handler على المعالج الذي تم إرجاعه
  • احفظ المعالج في مساحة تخزين العناصر settings
  • انتظِر إلى أن تنتهي عملية this.save لحفظ المحتوى في الملف الذي تم إنشاؤه حديثًا

بعد ذلك، ارجع إلى طريقة save، وتحقّق مما إذا كان handler متوفّرًا قبل محاولة الكتابة إليه، وإذا لم يكن متوفّرًا، انتظِر إلى أن تنتهي عملية this.saveAs.

4. عرض معاينة

باستخدام محرّر Markdown، يريد المستخدمون رؤية معاينة للناتج المعروض. باستخدام Window Management API، ستفتح معاينة للمحتوى المعروض على الشاشة الأساسية للمستخدم.

قبل البدء، أنشئ ملفًا js/preview.js، وأضِف إليه الرمز التالي لعرض معاينة عند تحميله:

import { openDB } from 'idb';
import { marked } from 'marked';

window.addEventListener('DOMContentLoaded', async () => {
  const preview = document.querySelector('.preview');
  const db = await openDB('settings-store');
  const content = (await db.get('settings', 'content')) || '';

  preview.innerHTML = marked(content);
});

يجب أن تتصرف المعاينة بالطرق التالية:

  • عندما ينقر المستخدم على زر المعاينة ولا تكون المعاينة مفتوحة، يجب أن يفتح المعاينة
  • عندما ينقر المستخدم على زر المعاينة وتكون المعاينة مفتوحة، يجب إغلاقها
  • عندما يغلق المستخدم تطبيق الويب التقدّمي أو يعيد تحميله، يجب إغلاق المعاينة

اتّبِع الخطوات التالية بالترتيب، وابدأ بتعديل طريقة preview في الفئة Actions في js/lib/actions.js لإجراء ما يلي:

  • الحصول على الشاشات المتاحة باستخدام Window Management API
  • فلترة الشاشات للعثور على الشاشة الرئيسية
  • افتح نافذة /preview بعنوان Markdown preview تشغل نصف العرض المتاح وجميع الارتفاع المتاح للشاشة الأساسية، مع ضبط موضعها بحيث تشغل النصف الأيمن الكامل المتاح من تلك الشاشة. لا تشمل السمات المتاحة المساحات المحجوزة من الشاشة، مثل شريط القوائم أو شريط الأدوات أو الحالة أو الموقع الجغرافي للنظام.
  • حفظ هذه النافذة المفتوحة في this.previewWindow
  • في أعلى الطريقة، تحقَّق مما إذا كان this.previewWindow متوفّرًا، وإذا كان متوفّرًا، أغلق النافذة وأزِل علامة this.previewWindow بدلاً من فتح معاينة للنافذة.

أخيرًا، نفِّذ ما يلي في نهاية الدالة الإنشائية للفئة Actions في js/lib/actions.js:

  • إغلاق this.previewWindow أثناء فعالية beforeunload

5- التركيز

أخيرًا، نريد أن نقدّم للمستخدمين وضع كتابة خالٍ من عوامل التشتيت. لا يعني وضع "عدم الإزعاج" إزالة الفوضى من التطبيقات الأخرى فحسب، بل يعني أيضًا منع شاشة المستخدم من الانتقال إلى وضع السكون. لإجراء ذلك، عليك استخدام Screen Wake Lock API.

سيعمل زر قفل التنشيط تمامًا مثل زر المعاينة، حيث يمكن التبديل بين حالتي التفعيل والإيقاف. لإجراء ذلك، في طريقة focus لفئة Actions في js/lib/actions.js، اتّبِع الخطوات التالية:

  • التحقّق مما إذا كان المستند يتضمّن عنصرًا بملء الشاشة
  • في حال ظهورها:
    • الخروج من وضع ملء الشاشة
    • إذا كان this.wakeLock متوفّرًا، أوقِف قفل التنشيط وأعِد ضبط this.wakeLock
  • إذا لم ينجح ذلك:
    • طلب عنصر تحكّم في قفل التنشيط وضبطه على this.wakeLock
    • طلب عرض نص المستند بملء الشاشة

6. تهانينا!

لقد تعلّمت كيفية إدارة ملفات النظام ودمج تطبيق الويب التقدّمي مع نظام باستخدام File System Access API وFile Handling API، وفتح نوافذ على شاشات مختلفة باستخدام Window Management API، ومنع الشاشة من الانتقال إلى وضع السكون باستخدام Screen Wake Lock API.

إنّ الدرس العملي التالي في السلسلة هو تضمين مشغّل الخدمات