الفصل العاشر: محرك التطبيق (الطرود البرمجية) Chapter 10: Essential Packages & Engine

التعرف على الأدوات الخارجية التي جعلت MRE CashBook نظاماً قوياً ومتكاملاً.

📦 فلسفة MRE Code في اختيار الحزم The Package Selection Philosophy

في MRE Code، مش بنضيف أي حزمة وخلاص. إحنا بنتبع معايير صارمة قبل إضافة أي dependency:

1

الشعبية (Popularity): لازم تكون الحزمة مدعومة من مجتمع كبير ولها تحديثات مستمرة.

2

الأداء (Performance): لازم يكون تأثيرها على حجم التطبيق وسرعته بسيط.

3

التوافق (Compatibility): لازم تدعم أحدث إصدارات Flutter وتشتغل على Android و iOS و Huawei بسلاسة.

🔄 إدارة الحالة: flutter_bloc The Architect: flutter_bloc

اختيار flutter_bloc ماجاش من فراغ. هو المترجم اللي بيحول ضغطات المستخدم لأفعال برمجية منظمة.

pubspec.yaml
flutter_bloc: ^9.1.1
equatable: ^2.0.8

ليه Equatable مع BLoC؟ عشان الباقة دي بتخلينا نقارن الحالات ببعضها بسهولة. لو الحالة الجديدة هي هي القديمة، الـ UI مش هيعمل Rebuild، وكدة بنوفر في استهلاك البطارية والمعالج.

بدون equatable، فلاتر هيفتكر إن الحالة اتغيرت حتى لو القيم هي هي، وده بيعمل استهلاك زيادة في الموارد.

💾 قاعدة البيانات: drift & drift_flutter The Persistence Engine: drift

من أصعب التحديات في تطبيقات الحسابات هي سرعة الوصول للداتا وحمايتها. drift (moor سابقاً) حلت المشكلة دي بذكاء.

// Example of an Entry Table in Drift
class Entries extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get amount => text()();
  DateTimeColumn get date => dateTime()();
  IntColumn get bookId => integer().references(Books, #id)();
}

Pro Tip: التطبيق بيستخدم drift_flutter اللي بتوفر بيئة تشغيل آمنة للـ SQLite على الموبايل وبتهندل الـ Database Path أوتوماتيك.

💉 حقن التبعيات: get_it Dependancy Injection: get_it

تخيل لو كل شاشة بتعرف نسخة جديدة من الـ Database؟! ده هيخلي الرام تنفجر. get_it بيضمن إن في نسخة واحدة بس (Singleton) التطبيق كله بيستخدمها.

injection_container.dart
final sl = GetIt.instance;

Future init() async {
  // Database instance
  sl.registerLazySingleton(() => AppDatabase());

  // Repositories
  sl.registerLazySingleton(() => EntryRepositoryImpl(sl()));

  // BLoCs
  sl.registerFactory(() => EntriesBloc(sl()));
}
🔄 كيف تتحدث الحزم مع بعضها؟ Package Interaction: The Harmony

الحزم مش جزر منعزلة، هي بتشتغل مع بعض في تناغم مذهل:

graph TD User((User)) -->|Tap| UI[Flutter UI] UI -->|Event| BLoC[flutter_bloc] BLoC -->|Query| Drift[Drift DB] Drift -->|Result| BLoC BLoC -->|New State| UI BLoC -->|Log| Firebase[Firebase Messaging] BLoC -->|Export| PDF[pdf / pdfx]
BLoC & Drift
التفاعلInteraction
الـ BLoC بيطلب الداتا من الـ Drift كـ Stream، وده بيخلي الشاشة تحدث نفسها أوتوماتيك أول ما الداتا تتغير في الداتابيز.BLoC requests data from Drift as a Stream, causing the UI to auto-update as soon as DB data changes.
بريق الواجهة: fl_chart & shimmer Visual Polish: User Experience

المستخدم بيحب يشوف فلوسه رايحة فين في رسم بياني، وبيكره يستنى شاشة بيضاء وهي بتحمل.

📈
fl_chart

بترسم الـ Spline Charts والـ Pie Charts بدقة عالية جداً وبدعم كامل للـ Interaction.

shimmer

بتقدم الـ Skeleton Loading (تأثير اللمعان) اللي بيخلي المستخدم يشعر إن التطبيق سريع جداً حتى لو في تأخير في الداتا.

📊
countup

بتخلي الأرقام "تعد" لما الشاشة تفتح، وده بيدي لمسة premium للتصميم.

🔍 تحليل عميق: الرسم والطباعة Deep Dive: Charts & PDF Engine

تعالوا نشوف كود حقيقي لاستخدام باقة fl_chart:

LineChart(
  LineChartData(
    gridData: FlGridData(show: false),
    titlesData: FlTitlesData(show: true),
    lineBarsData: [
      LineChartBarData(
        spots: [FlSpot(0, 100), FlSpot(1, 200), FlSpot(2, 150)],
        isCurved: true,
        barWidth: 4,
        color: context.colors.primary,
      ),
    ],
  ),
);

وبالنسبة للتقارير، بنستخدم pdf مع دعم الخطوط العربية:

final fontData = await rootBundle.load("assets/fonts/Cairo-Regular.ttf");
final ttf = pw.Font.ttf(fontData);

pdf.addPage(pw.Page(
  theme: pw.ThemeData.withFont(base: ttf),
  build: (context) => pw.Directionality(
    textDirection: pw.TextDirection.rtl,
    child: pw.Text("تقرير المصروفات لشهر مارس"),
  ),
));
🔥 الخدمات السحابية: Firebase Cloud Ecosystem: Firebase Suite

الأبليكيشن متكامل مع خدمات فيربيز لضمان أفضل تجربة:

PackageGoal (AR)
firebase_messagingإرسال عروض وتنبيهات فورية للمستخدمين.
firebase_crashlyticsرصد الأخطاء وإرسال تقارير مفصلة للمطورين.
📱 دعم أجهزة هواوي (HMS) Huawei Device Support (HMS)

بما إن في أجهزة كتير من هواوي مفيهاش خدمات جوجل، كان لازم ندعمها بشكل خاص:

🚀
huawei_push

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

🔐 باقات الأمان: التشفير والبصمة Security Stack: Encryption & Auth

الداتا المالية حساسة جداً، عشان كدة استخدمنا باقات مخصصة للأمان:

  • local_auth: بتشغل البصمة (Fingerprint) والـ Face ID.
  • encrypt: بتشفر البيانات الحساسة قبل ما تتحفظ في الـ Backup.
  • crypto: لإجراء عمليات الـ hashing والمقارنات الآمنة.
🛠️ قواعد صيانة الحزم The Maintenance Guide

إزاي بنحدث الحزم من غير ما المشروع يبوظ؟

1

التدرج: مابنحدثش كل الحزم مرة واحدة. بنحدث حزمة حزمة ونجرب.

2

Changelog: لازم نقرأ الـ README والـ Changelog عشان لو في Breaking Changes.

3

Tests: بنشغل الـ Unit Tests بعد كل تحديث عشان نضمن إن المنطق الأساسي ماتأثرش.

أسئلة شائعة Packages FAQ
ليه ما استخدمناش Provider بدل BLoC؟
Why BLoC over Provider?
الـ BLoC بيدينا فصل كامل (Clean Architecture) وتحكم أكبر في الحالات المعقدة زي تحميل الداتا من الداتابيز.
BLoC provides strict separation and better control over complex async states like DB loading.
هل إضافة باقات كتير بتقلل سرعة التطبيق؟
Does many packages slow down the app?
لو الباقات مش متوافقة أو حجمها عملاق أيوة. لكن إحنا بنختار باقات Lightweight ومجربة عشان نحافظ على الأداء.
Only if packages are heavy or incompatible. We choose lightweight, proven packages for performance.
💡 أفضل الممارسات (Best Practices) Package Usage Best Practices

عشان تضمن إن مشروعك يفضل "نظيف" وسهل الصيانة، اتبع القواعد دي:

1
Wrapper Classes

ماتستخدمش الباقة بشكل مباشر في الـ UI. اعمل كلاس (Wrapper) أو (Interface). ليه؟ عشان لو حبيت تغير الباقة في المستقبل، تغير في مكان واحد بس مش في كل المشروع.

2
Strict Versions

يفضل تستخدم إصدارات محددة (Pinned Versions) في الـ pubspec.yaml للمشاريع الكبيرة، عشان تضمن إن أي تحديث مفاجئ من صاحب الباقة ما يبوظش الكود بتاعك.

⚖️ مقارنة: ليه اخترنا Drift؟ Comparison: Why Drift?
DatabaseTypeProsCons
Drift (MRE Choice)Relational (SQL)Relational, Type-safeMore Boilerplate
HiveNoSQL (Key-Value)Super FastNo Relations
SharedPrefsKey-ValueSimpleFor Small Settings Only
🛠️ مشاكل البيئة الأصلية (Native) Native Environment Troubleshooting

الباقات اللي بتتعامل مع الـ hardware (زي البصمة أو الإشعارات) ساعات بتعمل مشاكل في الـ Build:

iOS
CocoaPods Issues

لو حصل خطأ في الـ iOS Build، جرب الكوماند ده:

cd ios && rm -rf Pods Podfile.lock && pod install && cd ..
Android
Gradle Configuration

باقات فيربيز ساعات بتحتاج إصدارات معينة من google-services في ملف build.gradle.

📖 قاموس المصطلحات Package Glossary
Dependencies
هي المكتبات اللي الكود بتاعك بيعتمد عليها عشان يشتغل.
Dev Dependencies
مكتبات بتحتاجها وقت التطوير بس (زي الاختبارات أو صناعة الكود) ومش بتنزل في النسخة النهائية للمستخدم.
semantic versioning (SemVer)
نظام ترقيم الإصدارات اللي بيتكون من 3 أرقام (Major.Minor.Patch).
📝 ملخص الفصل Chapter Summary

في الفصل ده عرفنا إن قوة MRE CashBook جاية من الاختيار الذكي للأدوات والتعاون المتناغم بين الباقات المختلفة.

LayerPrimary PackageRole
Stateflutter_blocManaging Logic & UI Updates
DatadriftSQLite Database Management
DIget_itGlobal Object Registry
UIfl_chartVisualization
ReportingpdfDocument Generation