تخطَّ إلى المحتوى

Flutter

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

التثبيت

لم تُنشر بعد

الحزمة غير منشورة على pub.dev بعد: تصلك مع حسابك، بالاسم أدناه.

dependencies:
  sanad_support: ^0.1.0

على Android يحتاج التطبيق إذن INTERNET، كأي تطبيق متصل بالشبكة.

الاستعمال

void main() {
  AppSupport.configure(const AppSupportOptions(
    appKey: 'pk_…',                          // تطبيقات الدعم ← المفاتيح (عام)
    apiUrl: 'https://<your support host>',
    appVersion: '4.2.0',
  ));
  runApp(const AppSupportScope(child: MyApp())); // فوق MaterialApp لترى اللقطة كل المسارات
}

// زر المساعدة الخاص بك:
IconButton(icon: const Icon(Icons.help_outline), onPressed: () => AppSupport.open(context));
  • غلّف التطبيق مرة واحدة بـ AppSupportScope فوق MaterialApp. ودونه يفتح الدعم، لكن بلا لقطة.
  • علّم ما يجب ألا يغادر الجهاز أبدًا بـ SupportMask(child: …) (أرقام البطاقات، والأرصدة، والبيانات الشخصية). وتُحجب العناصر المعلَّمة، وحقول النص المخفية (obscureText: true)، وعروض المنصة (WebView والخرائط) قبل أن يرى المستخدم المعاينة.
  • تتبع اللغة AppSupportOptions.language، ثم لغة التطبيق (ar أو en)، ثم لغته الأولى. والعربية من اليمين إلى اليسار بالكامل.

المحادثات ورسائل فريقك ومعاودة الاتصال

// بعد تسجيل الدخول: معرّفك الخاص للمستخدم (لا البريد ولا الاسم ولا معرّف الجهاز أبدًا)
await AppSupport.identify('u-8812');
// عند تسجيل الخروج
await AppSupport.identify(null);

// محادثات المستخدم مع فريقك، أو إحداها
AppSupport.openConversations(context);
AppSupport.openConversation(context, conversationId);

// ابحث الآن عن رسالة من فريقك (وتفعل الحزمة ذلك بنفسها أيضًا، أدناه)
final shown = await AppSupport.checkMessages(context);

// اختياري: سمِّ متصفّح التنقّل الجذري، حيث تظهر رسالة فريقك
runApp(AppSupportScope(navigatorKey: navigatorKey, child: MyApp(navigatorKey: navigatorKey)));
  • محادثات في الاتجاهين. كل رسالة يرسلها المستخدم تصبح محادثة يتابعها في التطبيق: القائمة (الأحدث أولًا، مفتوحة أو مغلقة)، وكل خيط بكل رسالة موسومة: موظف من فريقك، أو المساعد (آلي)، أو إشعار. ويرد المستخدم من الخيط، والرد يعيد فتح المحادثة المغلقة. وتُحدَّث الشاشات المفتوحة كل 15 ثانية ما دام التطبيق في الواجهة، ويعمل السحب للتحديث في أي وقت.
  • رسالة من فريقك، تظهر مرة واحدة. حين تفتح قاعدة استباقية محادثة مع المستخدم، تعرض الحزمة لافتة صغيرة، «لاحظنا مشكلة»، فوق شاشتك دون حجبها. تفتح الخيط، وتُغلق وحدها بعد 20 ثانية. وتبحث الحزمة عند بدء التطبيق، وعند عودته إلى الواجهة، وبعد identify(). ودون مستخدم معرَّف لا يُبحث عن شيء.
  • المستخدم المعرَّف يذهب مع كل رسالة وطلب معاودة اتصال، ويتيح لفريقك الوصول إليه في التطبيق. والمحادثات مرتبطة بالتثبيت: لا يراها تثبيت آخر، أيًّا كان معرّف المستخدم الذي يذكره.
  • معاودة الاتصال. من النموذج، يطلب «اطلب معاودة الاتصال» الرقم مع رمز الدولة (تعمل الأرقام العربية)، وموضوع المكالمة، ووقتًا مفضّلًا اختياريًا. ولا يُحفظ في طابور دون اتصال أبدًا: لا يُكتب رقم الهاتف في التخزين.
  • الموظف في المتناول دائمًا. «تحدّث إلى شخص» تحت إجابات المساعد دائمًا.

المساعد يشغّل مسارًا

حين يسرد تطبيق الدعم مسارات من روبوت المحادثة لمساعده، ويطابق السؤال أحدها، يعرضه المساعد: «أستطيع مساعدتك في ذلك هنا»، مع زر يبدؤه. ويعمل المسار في النافذة بعناصر أصلية: خيارات وبطاقات، ونعم ولا، ونماذج.

AppSupport.configure(AppSupportOptions(
  appKey: 'pk_…',
  apiUrl: 'https://<your support host>',
  userToken: await myServer.flowToken(),  // اختياري: المستخدم المسجّل (HS256 JWT، ساعة على الأكثر)
  refreshUserToken: myServer.flowToken,   // يُستدعى مرة حين ينتهي
));

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

ما تفعله، وما لا تفعله أبدًا

  • لا تفتح نفسها أبدًا ولا ترمي أي خطأ في تطبيقك. يكتمل open() بهدوء، وتذهب المشكلات إلى debugPrint. والضغطة الثانية أثناء الفتح أو والدعم مفتوح لا تفعل شيئًا. وAppSupport.close() يغلقه.
  • صورة ثابتة واحدة لتطبيقك، تُلتقط لحظة فتح الدعم، قبل رسم النافذة. لا تحتاج إذنًا ولا تُظهر طلبًا من النظام. ولا تُظهر أبدًا التطبيقات الأخرى أو شريط الحالة أو لوحة المفاتيح. ويستطيع المستخدم إخفاء أجزاء (تُحرق في البكسلات)، أو إزالتها، أو إرفاقها. وما تعرضه المعاينة هو تمامًا ما يُرفع.
  • الصورة في الذاكرة فقط. لا تُكتب على القرص أبدًا. وحين تتعذّر الخدمة، تُحفظ الرسالة (نصًا فقط) في طابور: 5 رسائل على الأكثر، لمدة تصل إلى 3 أيام، تُرسل عند configure() أو open() التالي، أو حين يعود التطبيق إلى الواجهة. ويخبر النموذج المستخدم بأن الرسالة ستُرسل دون اللقطة.
  • لا يُرسل إلا السياق المسموح به: إصدار التطبيق، وبنيته، واسم نظام التشغيل وإصداره الرئيسي، وهل الجهاز هاتف أو لوحي، واللغة. ويسرده النموذج تحت الرسالة.
  • يُستعمل معرّف تثبيت عشوائي لحدود المعدّل، ولإبقاء محادثات المستخدم على التثبيت الذي كُتبت منه.

سياسة الخصوصية لديك: نموذج

حين تتواصل مع الدعم في هذا التطبيق، نرسل رسالتك، وإن أبقيتهما مرفقتين، لقطة للشاشة التي كنت عليها ومحادثتك مع مساعد المساعدة. ونرسل أيضًا إصدار التطبيق ونظام التشغيل ونوع الجهاز. وترى كل ذلك قبل أن تضغط إرسال. وإن كنت مسجّل الدخول يذهب معرّف حسابك معها، لتصلك ردودنا ورسائلنا (مثلًا حين نلاحظ مشكلة أصابتك) في التطبيق. وإن طلبت أن نتصل بك، نرسل الرقم الذي تعطيه وموضوع المكالمة. وتُحفظ رسائل الدعم 180 يومًا بعد حلّها.