diff --git a/.gitignore b/.gitignore index faa2954..a6a980d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules dist types .rpt2_cache +.DS_Store diff --git a/README.md b/README.md index a2920b9..5caa889 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,21 @@ interface ICustomerDetailsSectionButtonClick { The `buttonId` property reflects the `id` specified for the button in the section definition. +#### `private_mode` + +Emitted when agent toggles private mode in Chats section. The handler gets the following payload: + +```ts +interface IPrivateModeData { + threads: { + [key: string]: boolean; + }; + source: 'chats'; +} +``` + +_String_ key is thread ID and boolean represents state of private mode. True means enabled private mode, false means disabled private mode. + ### Methods #### `getCustomerProfile(): ICustomerProfile | null` @@ -170,6 +185,17 @@ widget.modifySection(section); The `title` of a given section has to match the one specified in the initial state. Otherwise, the section won't change. Also, the Agent App ignores the commands without valid section definitions. Make sure that the definition you're sending is correct. +#### `getPrivateModeState(): IPrivateModeData | null` + +Gets threads with private mode recorded most recently. Returns the `IPrivateModeData` object, which is identical to the one emitted by the `private_mode` event or `null` (if no profile was registered). It may contain information about multiple threads, for example, when widget was initialized after agent has toggled private mode for some threads. + +```ts +{ + source: 'chats', + threads: { R80Q1FDEGX: true, R80Q1HDKP4: true } +} +``` + ## MessageBox widget (`IMessageBoxWidget`) ### Events @@ -182,6 +208,21 @@ Emitted after the widget is opened in the MessageBox. The handler will get a `IC Emitted after the message is sent by the agent. Keep in mind that the message has to be set with [`putMessage`] method in order to be sent. +#### `private_mode` + +Emitted when agent toggles private mode in Chats section. The handler gets the following payload: + +```ts +interface IPrivateModeData { + threads: { + [key: string]: boolean; + }; + source: 'chats'; +} +``` + +_String_ key is thread ID and boolean represents state of private mode. True means enabled private mode, false means disabled private mode. + ### Methods #### `putMessage(msg: IRichMessage | string): Promise` @@ -206,6 +247,17 @@ widget.putMessage(richMessage); Gets the customer profile recorded most recently. Returns the `ICustomerProfile` object, which is identical to the one emitted by the `customer_profile` event or `null` (if no profile was registered). +#### `getPrivateModeState(): IPrivateModeData | null` + +Gets threads with private mode recorded most recently. Returns the `IPrivateModeData` object, which is identical to the one emitted by the `private_mode` event or `null` (if no profile was registered). It may contain information about multiple threads, for example, when widget was initialized after agent has toggled private mode for some threads. + +```ts +{ + source: 'chats', + threads: { R80Q1FDEGX: true, R80Q1HDKP4: true } +} +``` + ### Rich Message object format - `custom_id`, `properties` and `elements` are optional diff --git a/package-lock.json b/package-lock.json index 247e924..e31c0d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@livechat/agent-app-sdk", - "version": "1.5.1", + "version": "1.5.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0a299d6..4c8baa3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@livechat/agent-app-sdk", - "version": "1.5.2", + "version": "1.6.0", "description": "SDK for extending LiveChat's Agent App", "license": "MIT", "repository": { diff --git a/src/index.ts b/src/index.ts index 69ca707..666bd35 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,3 +2,4 @@ export * from './widgets/details'; export * from './widgets/messagebox'; export * from './widgets/fullscreen'; export * from './widgets/shared/customer-profile'; +export * from './widgets/shared/private-mode'; diff --git a/src/utils/types.ts b/src/utils/types.ts index 601b43c..969cade 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1 +1,5 @@ export type Omit = Pick>; + +export interface KeyMap { + [key: string]: T; +} diff --git a/src/widgets/connection/constants.ts b/src/widgets/connection/constants.ts new file mode 100644 index 0000000..60bbd3a --- /dev/null +++ b/src/widgets/connection/constants.ts @@ -0,0 +1,10 @@ +export enum PluginType { + MessageBox = 'messagebox', + Details = 'details', + Fullscreen = 'fullscreen' +} + +export enum PluginMessage { + Inited = 'plugin_inited', + Loaded = 'plugin_loaded' +} diff --git a/src/widgets/details/details-widget.ts b/src/widgets/details/details-widget.ts index a595698..1f67e3f 100644 --- a/src/widgets/details/details-widget.ts +++ b/src/widgets/details/details-widget.ts @@ -1,6 +1,7 @@ import { withAmplitude } from '../shared/amplitude'; import { withCustomerProfile } from '../shared/customer-profile'; import { withRichMessages } from '../shared/rich-messages'; +import { withPrivateMode } from '../shared/private-mode'; import { createWidget } from '../shared/widget'; import { IConnection, createConnection } from '../connection'; import assertSection from './custom-sections'; @@ -9,6 +10,7 @@ import { IDetailsWidgetApi, ISection } from './interfaces'; +import { PluginMessage, PluginType } from '../connection/constants'; function DetailsWidget(connection: IConnection) { const base = createWidget( @@ -21,7 +23,7 @@ function DetailsWidget(connection: IConnection) { return connection.sendMessage('watch_messages'); }, refreshSession(): Promise { - return connection.sendMessage('plugin_loaded'); + return connection.sendMessage(PluginMessage.Loaded); }, modifySection(section: ISection): Promise { assertSection(section); @@ -30,7 +32,9 @@ function DetailsWidget(connection: IConnection) { } ); - const widget = withAmplitude(withRichMessages(withCustomerProfile(base))); + const widget = withAmplitude( + withRichMessages(withCustomerProfile(withPrivateMode(base))) + ); return widget; } @@ -42,7 +46,9 @@ export default function createDetailsWidget(): Promise { return createConnection() .then(connection => { widget = DetailsWidget(connection); - return connection.sendMessage('plugin_inited'); + return connection.sendMessage(PluginMessage.Inited, { + plugin_type: PluginType.Details + }); }) .then(() => widget); } diff --git a/src/widgets/fullscreen/fullscreen-widget.ts b/src/widgets/fullscreen/fullscreen-widget.ts index a6852ea..1fc80c5 100644 --- a/src/widgets/fullscreen/fullscreen-widget.ts +++ b/src/widgets/fullscreen/fullscreen-widget.ts @@ -2,6 +2,7 @@ import { createWidget } from '../shared/widget'; import { withAmplitude } from '../shared/amplitude'; import { IConnection, createConnection } from '../connection'; import { IFullscreenWidgetApi, IFullscreenWidgetEvents } from './interfaces'; +import { PluginMessage, PluginType } from '../connection/constants'; function FullscreenWidget(connection: IConnection) { const base = createWidget( @@ -22,7 +23,11 @@ export interface IFullscreenWidget extends ReturnType {} export default function createFullscreenWidget(): Promise { - return createConnection().then(connection => - FullscreenWidget(connection) - ); + return createConnection().then(connection => { + return connection + .sendMessage(PluginMessage.Inited, { + plugin_type: PluginType.Fullscreen + }) + .then(() => FullscreenWidget(connection)); + }); } diff --git a/src/widgets/messagebox/messagebox-widget.ts b/src/widgets/messagebox/messagebox-widget.ts index ec1b181..6a79202 100644 --- a/src/widgets/messagebox/messagebox-widget.ts +++ b/src/widgets/messagebox/messagebox-widget.ts @@ -1,6 +1,7 @@ import { createWidget } from '../shared/widget'; import { withAmplitude } from '../shared/amplitude'; import { withCustomerProfile } from '../shared/customer-profile'; +import { withPrivateMode } from '../shared/private-mode'; import { withRichMessages } from '../shared/rich-messages'; import { IConnection, createConnection } from '../connection'; import { @@ -8,6 +9,7 @@ import { IMessageBoxWidgetEvents, IRichMessage } from './interfaces'; +import { PluginType, PluginMessage } from '../connection/constants'; function MessageBoxWidget(connection: IConnection) { const base = createWidget( @@ -25,7 +27,9 @@ function MessageBoxWidget(connection: IConnection) { } ); - const widget = withAmplitude(withRichMessages(withCustomerProfile(base))); + const widget = withAmplitude( + withRichMessages(withCustomerProfile(withPrivateMode(base))) + ); return widget; } @@ -34,7 +38,11 @@ export interface IMessageBoxWidget extends ReturnType {} export default function createMessageBoxWidget(): Promise { - return createConnection().then(connection => - MessageBoxWidget(connection) - ); + return createConnection().then(connection => { + return connection + .sendMessage(PluginMessage.Inited, { + plugin_type: PluginType.MessageBox + }) + .then(() => MessageBoxWidget(connection)); + }); } diff --git a/src/widgets/shared/private-mode.ts b/src/widgets/shared/private-mode.ts new file mode 100644 index 0000000..215a51a --- /dev/null +++ b/src/widgets/shared/private-mode.ts @@ -0,0 +1,35 @@ +import { KeyMap } from '../../utils/types'; +import { WidgetMixin } from './widget'; + +export interface IPrivateModeData { + threads: KeyMap; + source: 'chats'; +} + +export interface IPrivateModeApi { + getPrivateModeState(): IPrivateModeData | null; +} + +export interface IPrivateModeEvents { + private_mode: IPrivateModeData; +} + +export const withPrivateMode: WidgetMixin< + IPrivateModeApi, + IPrivateModeEvents +> = widget => { + let threads = null; + + function onPrivateMode(privateMode: IPrivateModeData) { + threads = { ...threads, ...privateMode.threads }; + } + + widget.on('private_mode', onPrivateMode); + + return { + ...widget, + getPrivateModeState(): IPrivateModeData | null { + return { source: 'chats', threads }; + } + }; +};