مُنشئ HTML المخصص لصفحة البداية

:information_source: ملخص إضافة لـ Discourse تتيح تخصيص شاشة البداية (Splash Screen) باستخدام HTML و CSS محددين من قبل المسؤول.
:hammer_and_wrench: رابط المستودع https://github.com/VaperinaDEV/custom-splash-html-builder
:open_book: دليل التثبيت كيفية تثبيت الإضافات في Discourse

مرحباً :waving_hand:

لقد قمت بإنشاء إضافة صغيرة لـ Discourse تتيح تخصيص شاشة البداية باستخدام HTML و CSS محددين من قبل المسؤول، دون الحاجة إلى الحفاظ على نسخة معدلة من القالب الأساسي لشاشة البداية في Discourse.

كان الدافع الأصلي لإنشاء هذه الإضافة هو في الواقع أداء الأجهزة المحمولة.

أردت إنشاء شاشة بداية متحركة أكثر تطوراً، لكنني وجدت أن الرسوم المتحركة SVG المدعومة من قبل التنفيذ الحالي لشاشة البداية الأساسية في Discourse يمكن أن تسبب مشاكل غير متوقعة على الأجهزة المحمولة.

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

بعد تجربة أساليب مختلفة، وجدت أن نقل الرسوم المتحركة من عنصر SVG نفسه إلى عنصر HTML محيط به، مثل <div>، أحدث فرقاً كبيراً جداً.

بدلاً من تحريك محتويات SVG بشكل مستمر، يمكن أن يظل SVG ثابتاً بينما يقوم المتصفح بتحريك طبقة HTML الحاوية باستخدام تحويلات CSS.

هذا يمنح المتصفح فرصة أفضل بكثير للتعامل مع الرسوم المتحركة كعملية تركيب (Compositing) باستخدام عتاقة الرسومات في الجهاز.

كانت النتيجة رسوم متحركة أكثر سلاسة على الأجهزة المحمولة، دون التقطع والتجمد الذي كنت أراه مع النهج القائم على SVG.

كان هذا هو السبب الرئيسي لإنشاء هذه الإضافة.

قبل (SVG متحرك: تأخر وتوقف في الرسوم المتحركة)

بعد (HTML متحرك: رسوم متحركة سلسة)


المشكلة مع تحريك عناصر SVG

التنفيذ الأصلي لشاشة البداية ممتاز لشعار بسيط أو رسوم متحركة خفيفة نسبياً.

ومع ذلك، بمجرد أن تصبح الرسوم المتحركة أكثر تعقيداً، يمكن أن يصبح عرض SVG مكلفاً.

على سبيل المثال، قد يتطلب الرسوم المتحركة المطبقة مباشرة على SVG أو عناصره الداخلية من المتصفح معالجة أو إعادة رسم أجزاء من SVG بشكل متكرر أثناء التشغيل.

على الأجهزة المحمولة، يمكن أن يكون هذا ملحوظاً بشكل خاص.

أثناء الاختبار، رأيت حالات حيث كانت الرسوم المتحركة:

  • تصبح متقطعة بشكل مرئي
  • تتجمد مؤقتاً
  • تبدو وكأنها توقفت
  • تعمل بشكل أسوأ بكثير مما هي عليه على أجهزة سطح المكتب

كان الجزء المثير للاهتمام هو أن نفس الرسوم المتحركة البصرية يمكن أن تتصرف بشكل مختلف جداً اعتماداً على ما الذي يتم تحريكه فعلياً.


نقل الرسوم المتحركة إلى طبقة HTML

كان النهج الذي عمل بشكل أفضل هو إبقاء عنصر SVG نفسه ثابتاً ووضعه داخل عنصر HTML عادي.

على سبيل المثال:

<div class="logo-layer">
  <svg viewBox="0 0 500 500">
    ...
  </svg>
</div>

بدلاً من تحريك SVG، يتم تطبيق الرسوم المتحركة على الحاوية:

.logo-layer {
  animation: pulse 1.8s ease-in-out infinite;
  will-change: transform;
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(0.8);
  }

  50% {
    transform: scale(0.85);
  }
}

لا يتغير عنصر SVG نفسه.

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

أنتج هذا نتيجة أكثر سلاسة بشكل كبير على الأجهزة المحمولة.

لذلك فإن التمييز المهم هو:

النهج الأساسي:

SVG
 └── رسوم متحركة SVG
      └── يتم تحريك محتويات SVG

مقابل:

النهج المخصص:

طبقة HTML
 └── SVG
      └── تحويل CSS على طبقة HTML
           └── رسوم متحركة صديقة للمركب (Compositor)

هذا لا يضمن أن كل الرسوم المتحركة ستكون مسرعة بواسطة وحدة معالجة الرسومات (GPU). يقرر المتصفح في النهاية كيفية تركيب الرسوم المتحركة، ولكن في اختباراتي كان الفرق ملحوظاً جداً.


لماذا أنشأت أداة بناء HTML المخصص لشاشة البداية

n

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

لا يوفر قالب البداية القياسي مرونة كافية لهذا النوع من التنفيذ.

لرسوم متحركة أكثر تعقيداً، قد أحتاج إلى:

  • طبقات SVG متعددة
  • حاويات HTML متعددة
  • عناصر متحركة بشكل مستقل
  • إطارات رئيسية CSS مخصصة
  • توقيتات رسوم متحركة مختلفة
  • تموضع مخصص
  • ألوان مدركة للثيم (Theme-aware)
  • ترميز (Markup) مختلف تماماً عن شاشة البداية الافتراضية

لذلك، بدلاً من إنشاء تنفيذ شاشة بداية آخر مضمن في الكود (Hard-coded)، قررت جعل الجزء المرئي متاحاً من خلال إعدادين للموقع.

تضيف الإضافة:

splash_custom_html

ترميز HTML/SVG الذي يتم عرضه داخل شاشة البداية.

splash_custom_css

CSS المستخدم لشاشة البداية المخصصة، بما في ذلك الرسوم المتحركة، والإطارات الرئيسية، والتموضع، والسلوك المتجاوب.

هذا يجعل شاشة البداية قابلة للتخصيص بشكل فعال دون الحاجة إلى تعديل كود مصدر الإضافة في كل مرة تتغير فيها الرسوم المتحركة.


محرر المسؤول المدمج

توفر الإضافة أيضاً محرر مسؤول مدمج صغير لإدارة شاشة البداية المخصصة.

تضيف قسمًا مخصصًا باسم Splash HTML Builder في واجهة المسؤول في Discourse، مع محررات منفصلة لـ:

  • HTML المخصص
  • CSS المخصصn

يمكن حفظ التغييرات مباشرة من واجهة المسؤول دون الحاجة إلى تعديل إعدادات الموقع المقابلة يدوياً.

الإعدادات الأساسية لا تزال:

  • splash_custom_html
  • splash_custom_css

المحرر هو ببساطة واجهة أكثر ملاءمة لإدارتها.

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


مثال

يمكن أن تحتوي شاشة البداية المخصصة على طبقات مستقلة متعددة:

<div class="splash-logo-container">

  <div class="ring-layer">
    <svg viewBox="0 0 500 500">
      ...
    </svg>
  </div>

  <div class="logo-layer">
    <svg viewBox="0 0 500 500">
      ...
    </svg>
  </div>

</div>

ويمكن لكل طبقة أن يكون لها رسوم متحركة خاصة بها:

.ring-layer {
  animation: rotate 2.2s linear infinite;
  will-change: transform;
}

.logo-layer {
  animation: pulse 1.8s ease-in-out infinite;
  will-change: transform;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(0.8);
  }

  50% {
    transform: scale(0.85);
  }
}

تبقى عناصر SVG ثابتة بينما يتم تحريك طبقات HTML المحيطة بها.

هذا يجعل من الممكن إنشاء رسوم متحركة لشاشة البداية أكثر تعقيداً بشكل ملحوظ مع إبقاء عمل الرسوم المتحركة المكلف خارج عنصر SVG نفسه.


لماذا لا نكتفي ببساطة بتجاوز قالب شاشة البداية الأساسي؟

كان هدفاً مهماً آخر هو تجنب الحفاظ على نسخة من قالب شاشة البداية الأساسي في Discourse.

سيكون النهج المباشر هو تجاوز:

app/views/common/_discourse_splash.html.erb

ونسخ تنفيذ Discourse الحالي إلى الإضافة.

المشكلة هي أن هذا يخلق عبئاً صيانة.

إذا غيرت Discourse تنفيذ شاشة البداية في إصدار مستقبلي، ستحتوي الإضافة لا تزال على النسخة القديمة.

هذا قد يؤدي محتملاً إلى:

  • تفويت التغييرات الأساسية الجديدة
  • تفويت تحسينات الأداء
  • سلوك معطل بعد تحديث Discourse
  • الحاجة إلى مقارنة قالب الإضافة مع الأساسي يدوياً بعد كل تحديث
    n

أردت تجنب ذلك تماماً.


الاحتياط الأساسي (Core Fallback)

لذلك تدعم الإضافة شاشة بداية مخصصة مع احتياط أساسي.

تم تكوين HTML المخصص

إذا كان:

SiteSetting.splash_custom_html.present?

فإن الإضافة تعرض شاشة البداية المخصصة.

HTML المخصص فارغ

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

تحدد الإضافة الملف الأساسي الفعلي من تثبيت Discourse قيد التشغيل:

Rails.root/app/views/common/_discourse_splash.html.erb

وتعرض ذلك التنفيذ.

مفهومياً:

core_splash_path = Rails.root.join("app", "views", "common", "_discourse_splash.html.erb")

if File.exist?(core_splash_path)
  render inline: File.read(core_splash_path), type: :erb
end

هذا يعني أن الإضافة لا تحمل نسخة ثانية من قالب شاشة البداية الأساسي.


اعتبارات الأداء

لا تحاول الإضافة الادعاء بأن كل رسوم CSS المتحركة ستصبح مسرعة بواسطة وحدة معالجة الرسومات (GPU) بشكل سحري.

لا يزال المتصفح يقرر كيفية عرض وتركيب الرسوم المتحركة الفردية.

الهدف بدلاً من ذلك هو إعطاء المتصفح بنية أكثر ملاءمة للتركيب المعزز بالعتاقة:

  • إبقاء محتوى SVG ثابتاً
  • عزل العناصر المتحركة بشكل مستقل
  • تحريك طبقات HTML
  • تفضيل transform للحركة/التكبير/الدوران
  • تجنب عمليات إعادة الرسم المكلفة غير الضرورية
  • استخدام will-change حيث يناسب

على سبيل المثال:

.ring-layer {
  will-change: transform;
  animation: rotate 2.2s linear infinite;
}

عمل هذا النهج بشكل جيد بشكل خاص لحالة الاستخدام الخاصة بي وأزال التقطع على الأجهزة المحمولة الذي كنت أراه مع الرسوم المتحركة SVG الأصلية.


تفعيل أو تعطيل شاشة البداية المخصصة

توفر الإضافة أيضاً إعداد موقع باسم custom_splash_html_builder_enabled.

عند تعطيله، يتم استخدام شاشة البداية القياسية في Discourse بغض النظر عما إذا كان تم تكوين HTML أو CSS مخصص.

هذا يوفر مفتاح أمان إضافي لتعطيل شاشة البداية المخصصة مؤقتاً دون حذف HTML/CSS المحفوظ.

تتم عرض شاشة البداية المخصصة فقط عندما يكون كلاهما:

custom_splash_html_builder_enabled = true
splash_custom_html ليس فارغاً

بخلاف ذلك، يتم استخدام شاشة البداية الأساسية الحالية في Discourse.


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

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