Android
تضيف مكتبة Kavchat لنظام Android بوت الدعم القائم على السيناريوهات إلى تطبيقكم، مع مكوّنات Jetpack Compose وActivity للتطبيقات المبنية باستخدام Views. الردود متوقعة وتستمر في العمل دون اتصال بالإنترنت، اعتمادًا على آخر إصدار منشور. تتطلب Android 6.0 (API 23) أو أحدث.
تضم المكتبة مكوّنين: kavchat-engine، وهو نسخة Kotlin/JVM من محرك المحادثة، دون اعتماد على Android أو مكتبات خارجية، وkavchat، ويشمل الاتصال بالشبكة (HttpURLConnection)، والتخزين المؤقت على الجهاز (SharedPreferences)، ومكوّني Compose، KavchatChat وKavchatLauncher، بالإضافة إلى KavchatActivity.
التثبيت
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
// app/build.gradle.kts
dependencies {
implementation("com.kavchat:kavchat-android:0.0.11")
}تُوزَّع المكتبة عبر JitPack، لذا أضيفوا مستودعه مرة واحدة، بجانب google() وmavenCentral(). حزمة SDK مفتوحة المصدر بترخيص MIT: bitbucket.org/maxsave/kavchat-android.
تُعلن المكتبة بنفسها عن إذن INTERNET وعن KavchatActivity في ملف manifest الخاص بها. لا حاجة إلى إضافة أي شيء يدويًا.
الإعداد
استدعوا configure مرة واحدة في Application.onCreate:
class App : Application() {
override fun onCreate() {
super.onCreate()
Kavchat.configure(this, publicKey = "pk_live_...")
// Optional: Kavchat.configure(this, "pk_live_...", apiBase = "https://api.kavchat.com", locale = "he")
}
}يمكن تضمين المفتاح العام في التطبيق. أما المفتاح السري (sk_live_...)، فلا يجوز تضمينه فيه أبدًا.
Compose
زر عائم في الزاوية المحددة في لوحة التحكم، يفتح المحادثة بملء الشاشة:
KavchatOverlay(Modifier.fillMaxSize()) {
AppContent()
}يمكنكم أيضًا تحديد موضع الزر بأنفسكم، أو تضمين المحادثة في شاشة من تصميمكم:
KavchatLauncher() // com.kavchat.ui.KavchatLauncher
KavchatChat(Modifier.fillMaxSize()) // full chat, no close button
KavchatChat(Modifier.fillMaxSize(), onClose = { navController.popBackStack() })لفتح محادثة الزر العائم وإغلاقها من الكود، استخدموا Kavchat.controller.setPresented(true) وsetPresented(false).
Views (دون Compose في التطبيق)
Kavchat.open(context) // starts KavchatActivityمن Java: Kavchat.open(context);. تستخدم Activity مكوّنات Compose داخليًا، لكن تطبيقكم لا يحتاج إلى استخدامها.
رمز الهوية
عرّفوا المستخدم المسجّل دخوله باستخدام JWT يوقّعه خادمكم بالمفتاح السري (راجعوا التعرّف على المستخدمين). يُرسَل الرمز في الترويسة Authorization: Bearer <token>. يمكن للمستخدم الذي تم التعرّف عليه الاطلاع على الإصدارات المتاحة لمستخدمي الاختبار فقط، وإرسال نموذج التذكرة دون بريد إلكتروني أو رقم هاتف.
Kavchat.setUser(token = identityToken, name = "Dana") // after login
Kavchat.setUser(token = null) // after logoutيؤدي تبديل المستخدم إلى إعادة تحميل الإصدار وبدء محادثة جديدة، حتى لا تظهر محادثة مستخدم لدى مستخدم آخر.
شاشات التطبيق: onScreen
يطلب الزر من نوع screen في السيناريو من التطبيق فتح إحدى شاشاته. تُغلَق المحادثة أولًا (مربع حوار KavchatLauncher أو KavchatActivity)، حتى تظهر الشاشة:
Kavchat.onScreen = { screen, targetId ->
navController.navigate("$screen/${targetId.orEmpty()}") // e.g. "orders", "42"
}دون دالة معالجة، لا تفعل هذه الأزرار شيئًا. تفتح أزرار link روابط https فقط (في المتصفح) وروابط tel (في تطبيق الاتصال). ولتحليل البيانات، يُبلّغ Kavchat.onEvent عن Ready وUnavailable وOpen وClose وEffect وTicket.
قائمة الشاشات في المحرر
عرّفوا الشاشات التي يستطيع التطبيق فتحها مرة واحدة في Kavchat.configure(..., screens = ...) (النوع KavchatAppScreen). ترسل حزمة SDK القائمة إلى Kavchat تلقائيًا، ويعرض محرر السيناريوهات هذه الشاشات بأسمائها في قائمة منسدلة بدلًا من حقل نص حر. يطلب المحرر أيضًا معرّف عنصر عندما تحتاج إليه الشاشة، وينبّه إلى أي زر يؤدي إلى شاشة لم تُعرَّف. لا حاجة إلى كتابة قائمة الشاشات يدويًا في لوحة التحكم.
Kavchat.configure(
this, publicKey = "pk_live_...",
screens = listOf(
KavchatAppScreen("orders", "My orders"),
KavchatAppScreen("product", "Product page", needsTarget = true), // needs a targetId
),
)
// or later: Kavchat.registerScreens(listOf(...))idهو القيمة التي تصل إلىonScreen: أحرف لاتينية وأرقام و_و.و-، حتى 40 حرفًا.labelهو الاسم الذي يراه المسؤول، حتى 60 حرفًا. الحد الأقصى 100 شاشة. تُستبعَد السجلات غير الصالحة والمعرّفات المكررة.needsTarget: يحمل الزر أيضًا معرّف عنصر (مثل معرّف منتج)، ويصل إلىonScreenباسمtargetId.- تُرسَل القائمة في الخلفية بعد تحميل الإصدار، فقط عند تغيّرها أو مرة في الأسبوع. إذا فشل الإرسال، يحدث ذلك دون تنبيه، وتُعاد المحاولة عند التشغيل التالي. لا يظهر شيء للمستخدم.
- تظهر الشاشات المسجّلة في لوحة التحكم ضمن البوت، الإعدادات، "شاشات التطبيق"، مع المنصات التي أبلغت عن كل شاشة. ويمكن حذف الشاشة من هناك بعد إزالتها من التطبيق.
الألوان
تأتي الألوان من لوحة التحكم (primaryColor). يكون النص المعروض على لون العلامة التجارية أبيض أو شبه أسود بحسب تباين WCAG، ويُستبدَل اللون الفاتح جدًا للنص على خلفية بيضاء بلون شبه أسود في الروابط والأزرار. يأتي أيضًا اسم البوت والعنوان الفرعي والصورة وجهة الزر العائم (start أو end) من لوحة التحكم، لذا تتغير دون تحديث التطبيق. وتعتمد الأسطح وأنماط الخطوط على MaterialTheme الخاص بكم.
تظهر شارة "يعمل بواسطة Kavchat by maxsave" في جميع الخطط، مع رابط إلى kavchat.com. في Premium، يمكنكم إخفاؤها من إعدادات البوت.
اللغات والاتجاه من اليمين إلى اليسار
- لغة الواجهة هي قيمة
localeالمُمرَّرة إلىconfigure. إن لم تُمرَّر، تُستخدَم لغة الجهاز إذا توفرت لها ترجمة (he, en, ar, ru, es, fr, de, pt, it, tr)، ثم لغة السيناريو، وأخيرًا الإنجليزية. - تتم المطابقة دائمًا بلغة السيناريو (الكلمات الشائعة التي يجري تجاهلها، والبادئات في العبرية والعربية).
- في العبرية والعربية، تكون قيمة
LocalLayoutDirectionللمحادثة بأكملها RTL. لا يُعكَس شيء يدويًا: إذا أحطتم المكوّنات بحاويات، فاستخدمواstartوend. أبقواandroid:supportsRtl="true"في ملف manifest الخاص بالتطبيق.
إجابات الذكاء الاصطناعي (Premium)
لا حاجة إلى إعداد أي شيء في التطبيق. عند تفعيل إجابات الذكاء الاصطناعي في شاشة الإدارة (باستخدام مفتاحكم الخاص لدى مزوّد ذكاء اصطناعي)، يُرسَل السؤال الذي لا يجيب عنه أي سيناريو إلى Kavchat. وأثناء الانتظار، لمدة تصل إلى 20 ثانية، تُظهر المحادثة أن البوت يكتب. تظهر الإجابة كنص عادي مع تسمية صغيرة "إجابة الذكاء الاصطناعي" بلغة الواجهة، وتحتها زر لموضوع ذي صلة إن وُجد، وزر "التواصل مع الفريق".
إذا لم تتوفر إجابة، أو فشل الطلب، أو استغرق وقتًا أطول من المسموح، أو تجاوز الحد (10 إجابات لكل محادثة كل 15 دقيقة)، تعرض المحادثة رسالة "لم أجد إجابة" المعتادة. ويظل السؤال ظاهرًا في تقرير الأسئلة التي لم تُوجَد لها إجابة، وتُحفَظ إجابات الذكاء الاصطناعي في المحادثة المحفوظة مثل أي رسالة أخرى.
المحادثة مع موظف دعم
لا حاجة إلى إعداد أي شيء في التطبيق. عند تفعيل المحادثة مع موظفي الدعم في شاشة الإدارة، تعمل المحادثة داخل التطبيق تمامًا مثل أداة المحادثة في الموقع.
- يظهر الخيار فقط عندما تكون المحادثة مع موظفي الدعم مفعّلة في الإصدار المنشور. عندما يعرض البوت "التواصل مع الفريق"، تتحقق حزمة SDK من توفر موظف. تُحفَظ نتيجة التحقق لمدة 30 ثانية. إذا توفر موظف، يظهر قبله زر "محادثة مع موظف دعم". وإن لم يتوفر، يظهر نموذج التذكرة فقط، وفوقه سطر قصير يوضح السبب: خارج ساعات العمل (مع وقت العودة)، أو أن جميع الموظفين مشغولون.
- قبل المحادثة، يُملأ نموذج قصير: الاسم، والبريد الإلكتروني أو رقم الهاتف، والقسم (فقط عند وجود أكثر من قسم مفتوح)، ورسالة أولى (اختيارية). يجب على الزائر تقديم بريد إلكتروني أو رقم هاتف. أما المستخدم الذي تم التعرّف عليه برمز الهوية، فلا يُطلَب منه أي منهما. إذا لم يعد هناك موظف متاح عند الإرسال، يُفتَح نموذج التذكرة بالبيانات التي أُدخلت بالفعل.
- أثناء الانتظار، يظهر الوقت المتبقي حتى تتحول المحادثة إلى تذكرة، وزر "ترك رسالة بدلًا من ذلك". تُحدَّد مدة الانتظار في شاشة الإدارة، ومدتها الافتراضية 2 دقيقة. يمكن الكتابة أثناء الانتظار أيضًا، وسيرى الموظف الرسائل. إذا لم يتوفر أي موظف في الوقت المحدد، تُحفَظ المحادثة كتذكرة عادية ويظهر رقمها.
- أثناء المحادثة، يظهر اسم الموظف، وإشعار عند انضمام موظف (حتى بعد التحويل إلى موظف آخر)، ومؤشر عندما يكتب الموظف، وزر لإنهاء المحادثة. تقتصر الرسائل على نص عادي، حتى 2,000 حرف، دون روابط. تُعلَّم الرسالة التي لم تصل إلى الخادم بعد بعبارة "جارٍ الإرسال...". إذا فشل الإرسال عدة مرات، يمكن الضغط على الرسالة لإعادة المحاولة. لا تؤدي إعادة المحاولة إلى تكرار الرسالة.
- بعد كل انقطاع، تنتظر حزمة SDK قليلًا، وتجلب ما فات، ثم تعيد الاتصال. تزداد مدة الانتظار تدريجيًا. تظهر الرسائل دائمًا بالترتيب ودون تكرار. إذا تعذّر الاتصال المستمر (مثلًا بسبب خادم وكيل في الشركة)، تنتقل حزمة SDK مؤقتًا إلى الاستعلام المتكرر من الخادم.
- عندما ينتقل التطبيق إلى الخلفية، يُغلَق الاتصال. وعند العودة إلى التطبيق، تجلب حزمة SDK ما فات وتعيد الاتصال. تستمر المحادثة المفتوحة حتى بعد إغلاق التطبيق وإعادة تشغيله، ما دامت لم تمر 12 ساعة.
- لا توجد إشعارات فورية في هذا الإصدار. تصل الرسائل فقط عندما يكون التطبيق مفتوحًا. ويظهر الرد الذي أُرسل أثناء وجود التطبيق في الخلفية فور العودة إليه.
- تُحفَظ بيانات الوصول إلى المحادثة في الذاكرة. ولا تُحفَظ على الجهاز إلا مشفّرة بمفتاح من Android Keystore. ولا تُكتَب في عنوان URL أو سجل. تُحذَف البيانات عند انتهاء المحادثة أو تحوّلها إلى تذكرة أو انتهاء صلاحيتها، وكذلك عند تبديل المستخدم باستخدام
setUser.
يمكنكم استخدام Kavchat.controller.livePage لإبلاغ الموظف بالشاشة التي جاء منها المستخدم.
الأسئلة والشروط والعملاء المحتملون
لا حاجة إلى إعدادات في التطبيق. يمكن للسيناريو طلب بيانات (اسم، أو رقم هاتف، أو بريد إلكتروني، أو رقم، أو نص حر)، وتحديد كيفية المتابعة بحسب المعلومات المعروفة، وإرسال بيانات عميل محتمل.
- لوحة مفاتيح مناسبة: عندما ينتظر البوت إجابة، يعرض حقل النص لوحة مفاتيح للهاتف أو البريد الإلكتروني أو الأرقام. وعند السؤال عن الاسم، تنتقل لوحة المفاتيح إلى الأحرف الكبيرة في بداية كل كلمة. إذا كانت الإجابة غير صالحة، يرد البوت برسالة قصيرة بلغة المحادثة ويُميَّز الحقل. يظهر زر "تخطي" للأسئلة التي يمكن تجاوزها. وكتابة "إلغاء" بأي لغة مدعومة تُخرج المستخدم من السؤال.
- الهاتف: يُربَط الرقم الذي لا يبدأ بعلامة
+بالبلد الافتراضي لمساحة العمل (في إعدادات شاشة الإدارة). - العميل المحتمل: تعرض خطوة العميل المحتمل نص الموافقة مع زرّي "إرسال" و"لا، شكرًا"، ثم رسالة التأكيد. تُضاف بيانات العميل المحتمل إلى قائمة الانتظار على الجهاز وتُرسَل إلى الخادم. عند عدم وجود اتصال بالشبكة أو عدم توفر الخادم، تُعاد محاولات الإرسال (أيضًا عند التشغيل التالي وبعد
reload()). يتجاهل الخادم البيانات المكررة. - التعبئة المسبقة: يُملأ نموذج التذكرة ونموذج طلب المحادثة مع موظف بالاسم والبريد الإلكتروني ورقم الهاتف التي جُمعت. وتُرفَق جميع القيم التي جُمعت بالتذكرة أو بطلب المحادثة مع الموظف. تُطرَح أسئلة ما قبل المحادثة مع الموظف (Premium) قبل الاتصال.
- رمز الهوية: عند استخدام
setUser، تملأ حقولnameوemailوphoneفي الرمز إجابات الأسئلة المقابلة لها، فيتجاوزها البوت. - الشاشة الحالية: يمكن للشروط التحقق من الشاشة الحالية. اضبطوا
Kavchat.controller.livePage(مثلًا"checkout").
القيم التي تُجمَع هي معلومات شخصية. تبقى في المحادثة المحفوظة على الجهاز، ولا تُرسَل إلا ضمن بيانات العملاء المحتملين والتذاكر والمحادثات مع موظفي الدعم، ولا تُرسَل إلى التقارير أبدًا.
العمل دون اتصال والتخزين المؤقت
يُحفَظ آخر إصدار في SharedPreferences مع قيمة ETag الخاصة به، ويُعاد التحقق منه باستخدام If-None-Match (304) عند كل تشغيل. عند عدم وجود اتصال بالشبكة، تُستخدَم النسخة المحفوظة وتظهر رسالة توضح ذلك. عندما يكون البوت معطّلًا، أو متاحًا لمستخدمي الاختبار فقط، أو عند نفاد الحصة، لا يظهر شيء. تُحفَظ المحادثة المفتوحة حتى مرور 30 دقيقة دون نشاط، لذا لا يؤدي الخروج من المحادثة أو التطبيق إلى بدئها من جديد. يُرسَل تقرير بمسار المحادثة بعد ثانيتين من آخر إجراء، وفور انتقال التطبيق إلى الخلفية.