نظرة عامة

AmalApp (عمل ایپ) منصّة للأعمال الإسلامية اليومية بُنيت لجمهور غالبيته ناطق بالأردية على أجهزة Android منخفضة المواصفات (من فئة Samsung A07)، مع دعم iOS إلى جانبها. تقدّم محتوى دينيًا لكل يوم — القرآن والركوع والسُّنّة والصلاة والدعاء والأربعين حديثًا، لكلٍّ منها صور ومقاطع صوتية بأصوات متعدّدة — يتمحور حول نشاط يومي موجَّه مدّته نحو سبع دقائق. وحول هذه الحلقة الأساسية تقوم مجموعات للمتابعة والالتزام مع تتبّع الإنجاز اليومي، ومشغّل راديو إسلامي مباشر يرصد حضور المستمعين في الزمن الحقيقي، ومقاطع قصيرة، وأداة ملاحظات وبلاغات أخطاء داخل التطبيق. أمّا عمليات المحتوى وإدارة الوسائط والتحليلات فيتولّاها المشرفون عبر أدوات ويب مخصّصة، لا عبر ميزات مدمجة في التطبيق.

جولة توضيحية

2 مقاطع قصيرة عن المنتج — اسحب أو استخدم الأسهم للتنقل بينها.

01 / 02Product Showreel

التحدي

كان على المنتج أن يبدو عادةً يوميةً واحدة متماسكة، في حين أنّه في حقيقته نظام موزَّع: عميل جوال، وواجهة REST ذات إصدارات، ومخزن كائنات لكميات كبيرة من الصوت والصور، وواجهات تشغيلية منفصلة لمديري محتوى من غير المطوّرين. ونادرًا ما كانت المشكلات الصعبة تكمن في ميزة بعينها — بل كانت تسكن في المفاصل. كان على الجلسات أن تصمد أمام تدوير JWT الصارم دون أن تُخرج المستخدمين عند انقطاع شبكي عابر؛ وكان على بثّ الراديو المباشر أن يتتبّع المستمعين المتزامنين بدقّة حتى حين تُغلق التطبيقات قسرًا؛ وكان على محتوى كل يوم أن يُطابَق بين حاوية DigitalOcean Spaces وقاعدة البيانات ويُصدَّر بصيغة JSON مُهيّأة مسبقًا كي يفتح التطبيق بسرعة على اتصال ضعيف. وإنجاز ذلك عبر سبعة مستودعات يُنشَر كلٌّ منها على حدة، ولكلٍّ منها بيئة تشغيل وهدف نشر خاصّان به، هو القصّة الهندسية الحقيقية.

تصميم النظام

كيف يعمل

01/04
01

تسليم المحتوى اليومي

كيف يُنشأ المحتوى الإسلامي لكل يوم ويُطابَق مع التخزين ويُعرض بسرعة على تطبيق الجوال.

  1. 1يُحمّل مدير المحتوى عناصر كل نوع أو يعدّلها، مع صورها ومقاطعها الصوتية لكل صوت، عبر لوحة التحكّم وbucket-manager
  2. 2تُطابق أوامر إدارة items وItemBucketManager حاوية Spaces مع قاعدة البيانات
  3. 3يكتب json_generator تصديرات JSON يومية مُهيّأة مسبقًا إلى Spaces لتوزيعها عبر CDN
  4. 4يطلب تطبيق Flutter محتوى اليوم، فيستقبل JSON مُقدَّمًا عبر CDN مع روابط الوسائط ليعرضه بسرعة على اتصال بطيء
  5. 5يزامن متحكّم صوتي مشترك (CustomAudioPlayerController) صوت التلاوة مع الصورة الصحيحة، مستعينًا بحارس يميّز تغيير الصفحة البرمجي عن تغييرها بفعل المستخدم
02

دورة حياة الجلسة الموثَّقة

كيف تُصدَر رموز SimpleJWT وتُدوَّر وتُنهى عبر عميل Flutter.

  1. 1يسجّل المستخدم بحقل تواصل واحد يكتشف تلقائيًا البريد الإلكتروني أو رقم الهاتف الباكستاني أو اسم المستخدم، ويوجّه رمزًا لمرّة واحدة عبر Resend أو رسالة SMS
  2. 2عند تسجيل الدخول يُصدر SimpleJWT رمز وصول ورمز تجديد يحفظهما العميل ويرفقهما كرمز bearer مع كل طلب
  3. 3عند استجابة 401 يجدّد ApiClient الرمز لدى النظام الخلفي، ويحفظ رمز التجديد المُدوَّر، ثم يعيد إرسال الطلب الأصلي
  4. 4أخطاء بيانات الاعتماد تفرض تسجيل الخروج، بينما تحافظ أعطال 5xx أو الشبكة العابرة على الجلسة
  5. 5يمرّ تسجيل الخروج عبر SessionResetService الذي يمسح الرموز وحالة كل مستخدم في مكان واحد
03

تتبّع الحضور في الراديو المباشر

كيف يُحصى المستمعون المتزامنون للراديو في الزمن الحقيقي دون أن يتعطّل التشغيل مطلقًا.

  1. 1يفتح المستخدم محطّة، فيبثّ التطبيق عبر just_audio ويبدأ نبضات حضور لا يوقف فشلُها التشغيل
  2. 2يسجّل تطبيق presence الجلسة في مجموعات Redis المرتّبة، ويزيد عدّاد المستمعين المباشرين وعدّاد الفريدين يوميًا ضمن عملية compare-and-swap ذرّية مع حدٍّ أقصى لكل عنوان IP
  3. 3تُبقي النبضات الجلسة حيّة؛ وعند الإيقاف أو عند إغلاق قسري يُكتشف بانتهاء الصلاحية، تستقرّ العدّادات في تجميعات دائمة داخل Postgres
  4. 4وإذا لم يتوفّر Redis يتراجع التطبيق إلى أعداد مستمدّة من قاعدة البيانات دون تعطيل تشغيل الصوت
04

مجموعات المتابعة والتتبّع اليومي

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

  1. 1ينشئ المستخدم مجموعة أو ينضمّ إليها، ويوافق مشرف المجموعة على طلبات العضوية أو يزيلها
  2. 2يُسجَّل إنجاز كل مستخدم اليومي تسجيلًا شاملًا في UserDayTrack، ما يُنتج مصفوفات يومية وأسبوعية من الإثنين إلى الأحد
  3. 3يختزل GroupService العرض الأسبوعي في استعلام واحد محسّن، متفاديًا تشعّب استعلامات N+1 عبر الأعضاء
  4. 4يرسل المشرفون إشعارات تذكير تُصاغ وتُرسَل من dashboard_api عبر FCM

أبرز الميزات

  • محتوى إسلامي لكل يوم في ستّة أنواع (القرآن، الركوع، السُّنّة، الصلاة، الدعاء، الأربعون حديثًا) مع صور ومقاطع صوتية بأصوات متعدّدة، إضافة إلى نشاط يومي موجَّه مدّته نحو سبع دقائق
  • راديو إسلامي مباشر بمحطّات يحدّدها المشرف وجداول متكرّرة وتتبّع لحضور المستمعين في الزمن الحقيقي داخل Redis
  • مجموعات للمتابعة والالتزام مع تتبّع شامل لإنجاز كل مستخدم يوميًا وأسبوعيًا وإشعارات تذكير يرسلها المشرف
  • مقاطع قصيرة تعتمد على بيانات وصفية خارجية من YouTube Shorts، بطبقتَي serializer إحداهما للعموم والأخرى للمشرفين
  • ملاحظات وبلاغات أخطاء من مستخدمين موثَّقين، مع مرفقات صور وPDF ورسائل صوتية، وتحقّق من نوع MIME عبر البايتات السحرية يعمل بمبدأ الرفض عند الفشل
  • تجربة ثنائية اللغة بالأردية والإنجليزية مع إشعارات FCM وتذكيرات محلّية مجدولة مضبوطة لأجهزة Android منخفضة المواصفات
  • لوحة تحكّم إدارية بـ Next.js تجمع مؤشّرات الأداء وحالة النظام وتحليلات GA4 وعمليات المحتوى خلف نقاط وصول JWT مقصورة على المشرفين
  • مدير حاويات مستقلّ ومعزول ببيانات اعتماد خاصّة، يمنح مديري المحتوى من غير المطوّرين وصولًا محدود النطاق إلى DigitalOcean Spaces

Outcomes

  • سلّمتُ منصّة متكاملة عبر سبعة مستودعات — تطبيق Flutter، ونظام خلفي بـ Django/DRF، وواجهتان إداريتان بـ Next.js، وصفحة هبوط ثابتة، ومنظومة مراقبة بـ Prometheus/Grafana — ضمن مسار تكامل مستمر واحد بفرعٍ لكل بيئة
  • هندستُ نموذج جلسة JWT مُحصَّنًا للإنتاج على جانب العميل، يحفظ رموز التجديد المُدوَّرة ويميّز أخطاء بيانات الاعتماد عن الأعطال العابرة، وحلّ ذلك خللًا حقيقيًا في تسجيل الخروج ناتجًا عن تدوير SimpleJWT وإدراج الرموز في القائمة السوداء
  • بنيتُ نظام حضور في الزمن الحقيقي فوق مجموعات Redis المرتّبة، بعدٍّ ذرّي بأسلوب compare-and-swap وتجميعات في Postgres، يظلّ دقيقًا حتى مع التطبيقات المُغلقة قسرًا ويصمد أمام انقطاعات Redis
  • حقّقتُ تحسينًا قابلًا للقياس في الاستعلامات — إحصاءات items انخفضت من 13 استعلامًا إلى استعلامين، وتتبّع المجموعات الأسبوعي من 7 إلى 1 — عبر فهارس مركّبة واستخدام واسع لـ select_related وprefetch_related

أعمال أخرى

Mashoor preview
سوق متعدّد البائعين

Mashoor

سوق متعدّد البائعين ثنائي اللغة وجاهز للاتجاه من اليمين إلى اليسار، لمنتجات باكستان الإقليمية المميّزة

عرض المشروع