Assist

كيفية إعداد OpenReplay Assist ودعم المستخدمين النهائيين من خلال الشاشة المباشرة وWebRTC.

Assist

يتيح لك OpenReplay Assist دعم مستخدميك من خلال رؤية شاشتهم المباشرة والانضمام فوراً إلى مكالمة (WebRTC) معهم دون الحاجة إلى أي برنامج مشاركة شاشة تابع لجهة خارجية.

npm i @openreplay/tracker-assist

باستخدام مقتطف JavaScript

Section titled باستخدام مقتطف JavaScript

إذا كان متتبّع OpenReplay الخاص بك مُعدّاً باستخدام مقتطف JS، فما عليك سوى استبدال ظهور .../openreplay.js بـ .../openreplay-assist.js. فيما يلي مثال على الشكل الذي يجب أن يبدو عليه السكربت بعد التغيير:

<!-- OpenReplay Tracking Code -->
<script>
var initOpts = { projectKey: "GxPpaDARdn2345fgt321" };
var startOpts = { userID: "" };
(function(A,s,a,y,e,r){
  r=window.OpenReplay=[e,r,y,[s-1, e]];
  s=document.createElement('script');s.src=A;s.async=!a;
  ...
})("//static.openreplay.com/latest/openreplay-assist.js", 1, 0, initOpts, startOpts);
</script>

قم بتهيئة المتتبّع ثم حمّل الإضافة @openreplay/tracker-assist.

إذا كان موقعك تطبيقاً ذا صفحة واحدة (SPA)

Section titled إذا كان موقعك تطبيقاً ذا صفحة واحدة (SPA)
import trackerAssist from '@openreplay/tracker-assist';
import { tracker } from '@openreplay/tracker';

tracker.configure({
  projectKey: 'YOUR_PROJECT_KEY',
  ingestPoint: "https://openreplay.mydomain.com/ingest", // when dealing with the self-hosted version of OpenReplay
});
tracker.use(trackerAssist(options)); // check the list of available options below

tracker.start();

إذا كان تطبيق الويب الخاص بك يُعرَض من جانب الخادم (SSR)

Section titled إذا كان تطبيق الويب الخاص بك يُعرَض من جانب الخادم (SSR)

اتّبع المثال أدناه إذا كان تطبيقك يستخدم SSR. تأكّد من استدعاء tracker.start() بمجرد أن يكون التطبيق في بيئة المتصفح (أي عبر useEffect أو componentDidMount).

import trackerAssist from '@openreplay/tracker-assist';
import { tracker } from '@openreplay/tracker';

tracker.configure({
  projectKey: 'YOUR_PROJECT_KEY',
  ingestPoint: "https://openreplay.mydomain.com/ingest", // when dealing with the self-hosted version of OpenReplay
});
tracker.use(trackerAssist(options)); // check the list of available options below

//...
function MyApp() {
  useEffect(() => { // use componentDidMount in case of React Class Component
    tracker.start();
  }, [])
//...
}

تدعم إضافة assist الخيارات التالية:

trackerAssist({
  callConfirm?: string|ConfirmOptions;
  controlConfirm?: string|ConfirmOptions;
  config?: object;
  onAgentConnect?: () => (()=>void | void);
  onCallStart?: () => (()=>void | void);
  onRemoteControlStart?: () => (()=>void | void);
  onCallDeny?: () => any;
  onRemoteControlDeny?: (agentInfo: Record<string, any>) => any;
  onRecordingDeny?: (agentInfo: Record<string, any>) => any;
  onDragCamera?: (dx: number, dy: number) => any;
  callUITemplate?: string
  /** 
   * enables gzip compression for big batches on client side
   * */
  compressionEnabled: boolean;
  /**
   * Minimum amount of MESSAGES in a batch to trigger compression run
   * @default 5000
   * */
  compressionMinBatchSize: number;
  /**
   * Show only the first part of an agent's name in the call popup
   * (e.g. "One Two" -> "One").
   * @default false
   */
  agentShortNames: boolean;
  /**
   * Postpone assist start until a userID is set on the session.
   * @default false
   */
  ignoreAnonymous: boolean;
  /**
   * When assist connects to the server:
   * - Autostart.Auto (default): always on tracker start.
   * - Autostart.Disabled: only via an explicit start() call.
   * - Autostart.Continuation: only via assist.start(), but the choice is remembered
   *   in sessionStorage so it auto-continues across page reloads until assist.stop().
   * @default Autostart.Auto
   */
  autostart: Autostart;
  /**
   * Require explicit user confirmation before anything is shared with an
   * agent: assist starts and opens the socket as usual, but no messages are
   * sent through it until the user approves the confirmation popup, which is
   * shown as soon as the first agent connects to the session. The approval
   * is remembered per-tab (sessionStorage) until stop() is called.
   * @default false
   */
  requestConfirm: boolean;
  /** Text/style customization for the session view confirmation popup. */
  sessionConfirm?: ConfirmOptions;
  /** Called when the user approves session viewing (requestConfirm mode). */
  onSessionConfirmApprove?: (agentInfo: Record<string, any>) => any;
  /** Called when the user denies session viewing (requestConfirm mode). */
  onSessionConfirmDeny?: (agentInfo: Record<string, any>) => any;
})

تخصيص عناصر الواجهة (Widgets)

Section titled تخصيص عناصر الواجهة (Widgets)

يمكن تخصيص العرض المباشر والتحكم عن بُعد وكذلك عناصر واجهة المكالمة، تلك التي يراها المستخدم النهائي، تخصيصاً كاملاً.

عنصر واجهة العرض المباشر

Section titled عنصر واجهة العرض المباشر

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

يتم تذكّر الموافقة لكل تبويب (في sessionStorage) حتى يتم استدعاء stop()، الذي يُلغيها، بحيث سيطلب start() التالي التأكيد مجدداً.

tracker.use(trackerAssist({
  requestConfirm: true,
  sessionConfirm: { text: 'A support agent would like to view your screen. Allow?' },
  onSessionConfirmApprove: ({ email, name, query }) => console.log("Session viewing approved"),
  onSessionConfirmDeny: ({ email, name, query }) => console.log("Session viewing denied"),
}));

يمكن تخصيص نص النافذة المنبثقة ونمطها عبر خيار sessionConfirm، الذي يأخذ كائن ConfirmOptions التالي:

type ConfirmOptions = {
  text?:string,
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
  confirmBtn?: ButtonOptions, 
  declineBtn?: ButtonOptions
}

type ButtonOptions = HTMLButtonElement | string | {
  innerHTML?: string, // to pass an svg string or text
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
}

عنصر واجهة التحكم عن بُعد

Section titled عنصر واجهة التحكم عن بُعد

يمكن تخصيص نص النافذة المنبثقة ونمطها عبر خيار controlConfirm، الذي يأخذ كائن ConfirmOptions التالي:

type ConfirmOptions = {
  text?:string,
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
  confirmBtn?: ButtonOptions, 
  declineBtn?: ButtonOptions
}

type ButtonOptions = HTMLButtonElement | string | {
  innerHTML?: string, // to pass an svg string or text
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
}

عنصر واجهة المكالمة

Section titled عنصر واجهة المكالمة

يمكن تخصيص نص النافذة المنبثقة ونمطها عبر خيار callConfirm، الذي يأخذ كائن ConfirmOptions التالي:

type ConfirmOptions = {
  text?:string,
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
  confirmBtn?: ButtonOptions, 
  declineBtn?: ButtonOptions
}

type ButtonOptions = HTMLButtonElement | string | {
  innerHTML?: string, // to pass an svg string or text
  style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'})
}

من الممكن تخصيص كل جانب من جوانب عنصر الواجهة هذا عبر مجموعة ids وclasses التالية. تُستخدم Ids كنقاط ربط للأزرار/العناصر الفردية، بينما يمكن استخدام classes لحاويات المجموعات.

نوع HTMLالاسم/الأسماءالوصف
idor-assistحاوية عنصر الواجهة
classcard وborder-dark وshadow وdrag-areaأنماط حدود البطاقة وظلّها
idcontrolsحاوية الجزء الخاص بالمكالمة داخل عنصر الواجهة
classcard-headerأنماط رأس بطاقة عنصر واجهة المكالمة (تلك التي تعرض اسم الوكيل بجوار المؤقّت)
idagent-nameحاوية اسم الوكيل
iddurationحاوية المؤقّت
idvideo-containerحاوية بثّ الفيديو الخاص بالمستخدم نفسه
idremote-streamبثّ الفيديو الخاص بالوكيل
classcard-footerحاوية أزرار كتم الصوت والفيديو وإنهاء المكالمة
idaudio-btnزر كتم الصوت
idvideo-btnزر الفيديو
idend-call-btnزر إنهاء المكالمة
idremote-control-rowصفّ عناصر التحكم عن بُعد
idend-control-btnمعرّف زر إنهاء التحكم

دوال الاستدعاء (Callbacks)

Section titled دوال الاستدعاء (Callbacks)

فيما يلي قائمة بجميع دوال الاستدعاء:

  • callConfirm: تخصيص نص و/أو تخطيط النافذة المنبثقة لطلب المكالمة.
  • controlConfirm: تخصيص نص و/أو تخطيط النافذة المنبثقة لطلب التحكم عن بُعد.
  • config: يحتوي على إعدادات مخصّصة لخادم ICE/TURN. القيمة الافتراضية هي { 'iceServers': [{ 'urls': 'stun:stun.l.google.com:19302' }], 'sdpSemantics': 'unified-plan' }.
  • onAgentConnect: () => (()=>void | void): تُستدعى دالة الاستدعاء هذه بمجرد بدء جلسة مباشرة وتعيد تفاصيل الوكيل (email والاسم وquery). يمكنها أيضاً إعادة onAgentDisconnect التي سيتم استدعاؤها عند قطع اتصال الجلسة. في حال وجود اتصال غير مستقر، قد تُستدعى عدة مرات. فيما يلي مثال:
onAgentConnect = ({ email, name, query }) => {
  console.log("Live session started")
  const onAgentDisconnect =  () => console.log("Live session stopped")
  return onAgentDisconnect
}
  • onCallStart: ({ email, name, query }) => (()=>void | void): تُستدعى دالة الاستدعاء هذه بمجرد بدء مكالمة (webRTC) وتعيد تفاصيل الوكيل (email والاسم وquery). يمكنها أيضاً إعادة onCallEnd التي سيتم استدعاؤها عند انتهاء المكالمة. في حال وجود اتصال غير مستقر، قد تُستدعى عدة مرات. فيما يلي مثال:
onCallStart: () => {
  console.log("Call started")
  const onCallEnd = () => console.log("Call ended")
  return onCallEnd
}
  • onRemoteControlStart: ({ email, name, query }) => (()=>void | void): تُستدعى دالة الاستدعاء هذه بمجرد بدء جلسة تحكم عن بُعد وتعيد تفاصيل الوكيل (email والاسم وquery). يمكنها أيضاً إعادة onRemoteControlEnd التي سيتم استدعاؤها عند إلغاء أذونات التحكم عن بُعد. فيما يلي مثال:
onRemoteControlStart: () => {
  console.log("Remote control started")
  const onControlEnd = () => console.log("Remote control ended")
  return onControlEnd
}
  • onCallDeny?: () => any;: تُستدعى دالة الاستدعاء هذه عندما يرفض المستخدم المكالمة أثناء مرحلة الطلب.
onCallDeny: () => {
  console.log("Call denied")
}
  • onRemoteControlDeny?: (agentInfo: Record<string, any>) => any;: تُستدعى دالة الاستدعاء هذه عندما يرفض المستخدم جلسة التحكم عن بُعد أثناء مرحلة الطلب وتعيد تفاصيل الوكيل (email والاسم وquery).
onRemoteControlDeny: ({ email, name, query }) => {
  console.log("Remote control request denied for", email)
}
  • onRecordingDeny?: (agentInfo: Record<string, any>) => any;: تُستدعى دالة الاستدعاء هذه عندما يرفض المستخدم جلسة التسجيل أثناء مرحلة الطلب وتعيد تفاصيل الوكيل (email والاسم وquery).
onRecordingDeny: ({ email, name, query }) => {
  console.log("Recording session denied")
 
}
  • onSessionConfirmApprove?: (agentInfo: Record<string, any>) => any;: تُستدعى دالة الاستدعاء هذه عندما يوافق المستخدم على مشاهدة الجلسة (في وضع requestConfirm) وتعيد تفاصيل الوكيل (email والاسم وquery).
onSessionConfirmApprove: ({ email, name, query }) => {
  console.log("Session viewing approved for", email)
}
  • onSessionConfirmDeny?: (agentInfo: Record<string, any>) => any;: تُستدعى دالة الاستدعاء هذه عندما يرفض المستخدم مشاهدة الجلسة (في وضع requestConfirm) وتعيد تفاصيل الوكيل (email والاسم وquery).
onSessionConfirmDeny: ({ email, name, query }) => {
  console.log("Session viewing denied")
}
  • onDragCamera?: (dx: number, dy: number) => any;: تتوقّع هذه الدالة معالِجاً يحدّد سلوك زر الفأرة المضغوط داخل لوحة Three.js canvas للتحكم عن بُعد. يستقبل المعالِج dx وdy، اللذين يشيران إلى مقادير حركة الفأرة.
onDragCamera: (dx, dy) => {
  moveCamera(dx, dy)
}

تُعيد tracker.use() نسخة assist، التي تكشف طرقاً للتحكّم في assist أثناء التشغيل:

const assist = tracker.use(trackerAssist(options));

assist.stop();
assist.start();
  • start(): يعيد تشغيل assist (أو يشغّله). لا يفعل شيئاً إذا لم يكن المتتبّع نفسه نشطاً بعد (سيبدأ assist مع المتتبّع). في وضع Autostart.Continuation، يحفظ علامة في sessionStorage بحيث يستمر assist تلقائياً عبر عمليات إعادة تحميل الصفحة. كما أن استدعاء start() الصريح يتجاوز أي تأجيل بسبب ignoreAnonymous.
  • stop(): يوقف assist عن طريق قطع اتصال المقبس (socket) وتنظيف جميع الاتصالات. لن يُعاد تشغيل assist تلقائياً حتى يتم استدعاء start(). في وضع Autostart.Continuation، يمسح هذا أيضاً العلامة المحفوظة، بحيث لن تستمر إعادة التحميل تلقائياً. في وضع requestConfirm، يُلغي أيضاً موافقة المستخدم، بحيث سيطلب start() التالي التأكيد مجدداً.

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