@botpress/webchat 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +31 -0
  2. package/dist/components/Composer.d.ts +4 -5
  3. package/dist/components/Composer.js +13 -23
  4. package/dist/components/Container.d.ts +1 -1
  5. package/dist/components/Container.js +1 -6
  6. package/dist/components/ConversationList.d.ts +1 -1
  7. package/dist/components/ConversationList.js +5 -46
  8. package/dist/components/Header.d.ts +1 -3
  9. package/dist/components/Header.js +17 -64
  10. package/dist/components/VoiceRecorder.js +6 -2
  11. package/dist/components/common/{Avatar.d.ts → Avatar/index.d.ts} +0 -0
  12. package/dist/components/common/Avatar/index.js +13 -0
  13. package/dist/components/common/{BotInfo.d.ts → BotInfo/index.d.ts} +3 -3
  14. package/dist/components/common/BotInfo/index.js +102 -0
  15. package/dist/components/common/ConfirmDialog/index.d.ts +11 -0
  16. package/dist/components/common/ConfirmDialog/index.js +78 -0
  17. package/dist/components/common/Dialog/index.d.ts +17 -0
  18. package/dist/components/common/Dialog/index.js +57 -0
  19. package/dist/components/common/ToolTip/index.d.ts +10 -0
  20. package/dist/components/common/ToolTip/index.js +163 -0
  21. package/dist/components/common/ToolTip/utils.d.ts +15 -0
  22. package/dist/components/common/ToolTip/utils.js +78 -0
  23. package/dist/components/messages/InlineFeedback.d.ts +2 -1
  24. package/dist/components/messages/Message.js +2 -25
  25. package/dist/components/messages/MessageGroup.d.ts +1 -13
  26. package/dist/components/messages/MessageGroup.js +6 -40
  27. package/dist/components/messages/MessageList.d.ts +1 -1
  28. package/dist/components/messages/MessageList.js +8 -31
  29. package/dist/core/api.d.ts +4 -18
  30. package/dist/core/api.js +25 -150
  31. package/dist/core/constants.d.ts +4 -32
  32. package/dist/core/constants.js +18 -32
  33. package/dist/core/socket.d.ts +1 -12
  34. package/dist/core/socket.js +7 -73
  35. package/dist/{components/Stylesheet.d.ts → icons/Cancel.d.ts} +2 -2
  36. package/dist/icons/Cancel.js +10 -0
  37. package/dist/icons/Microphone.d.ts +5 -0
  38. package/dist/icons/Microphone.js +12 -0
  39. package/dist/index.d.ts +2 -8
  40. package/dist/index.js +9 -29
  41. package/dist/main.d.ts +2 -2
  42. package/dist/main.js +100 -168
  43. package/dist/store/composer.js +3 -6
  44. package/dist/store/index.d.ts +8 -18
  45. package/dist/store/index.js +98 -136
  46. package/dist/store/view.d.ts +3 -6
  47. package/dist/store/view.js +6 -23
  48. package/dist/translations/index.d.ts +3 -1
  49. package/dist/translations/index.js +44 -4
  50. package/dist/typings.d.ts +121 -71
  51. package/dist/utils/analytics.d.ts +5 -0
  52. package/dist/utils/analytics.js +37 -0
  53. package/dist/utils/index.d.ts +3 -0
  54. package/dist/utils/index.js +27 -0
  55. package/dist/utils/storage.d.ts +16 -0
  56. package/dist/utils/storage.js +129 -0
  57. package/package.json +4 -3
  58. package/dist/components/ContextMenu.d.ts +0 -2
  59. package/dist/components/ContextMenu.js +0 -33
  60. package/dist/components/OverridableComponent.d.ts +0 -24
  61. package/dist/components/OverridableComponent.js +0 -50
  62. package/dist/components/Stylesheet.js +0 -7
  63. package/dist/components/common/Avatar.js +0 -29
  64. package/dist/components/common/BotInfo.js +0 -110
  65. package/dist/icons/CloseChat.d.ts +0 -6
  66. package/dist/icons/CloseChat.js +0 -9
  67. package/dist/icons/Send.d.ts +0 -6
  68. package/dist/icons/Send.js +0 -8
  69. package/dist/utils.d.ts +0 -8
  70. package/dist/utils.js +0 -111
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getUserLocale = exports.defaultLocale = exports.translations = void 0;
6
+ exports.isRTLLocale = exports.setUserLocale = exports.getUserLocale = exports.defaultLocale = exports.translations = void 0;
7
7
  require('@formatjs/intl-pluralrules/polyfill');
8
8
  require('@formatjs/intl-pluralrules/locale-data/ar');
9
9
  require('@formatjs/intl-pluralrules/locale-data/de');
@@ -25,19 +25,43 @@ const ru_json_1 = __importDefault(require("./ru.json"));
25
25
  const uk_json_1 = __importDefault(require("./uk.json"));
26
26
  const DEFAULT_LOCALE = 'en';
27
27
  exports.defaultLocale = DEFAULT_LOCALE;
28
- const STORAGE_KEY = 'bp/channel-web/user-lang';
28
+ const USER_LANG_STORAGE_KEY = 'user-lang';
29
29
  const translations = { en: en_json_1.default, fr: fr_json_1.default, pt: pt_json_1.default, es: es_json_1.default, ar: ar_json_1.default, ru: ru_json_1.default, uk: uk_json_1.default, de: de_json_1.default, it: it_json_1.default };
30
30
  exports.translations = translations;
31
+ const rtlLocales = [
32
+ 'ae' /* Avestan */,
33
+ 'ar' /* 'العربية', Arabic */,
34
+ 'arc' /* Aramaic */,
35
+ 'bcc' /* 'بلوچی مکرانی', Southern Balochi */,
36
+ 'bqi' /* 'بختياري', Bakthiari */,
37
+ 'ckb' /* 'Soranî / کوردی', Sorani */,
38
+ 'dv' /* Dhivehi */,
39
+ 'fa' /* 'فارسی', Persian */,
40
+ 'glk' /* 'گیلکی', Gilaki */,
41
+ 'he' /* 'עברית', Hebrew */,
42
+ 'ku' /* 'Kurdî / كوردی', Kurdish */,
43
+ 'mzn' /* 'مازِرونی', Mazanderani */,
44
+ 'nqo' /* N'Ko */,
45
+ 'pnb' /* 'پنجابی', Western Punjabi */,
46
+ 'ps' /* 'پښتو', Pashto, */,
47
+ 'sd' /* 'سنڌي', Sindhi */,
48
+ 'ug' /* 'Uyghurche / ئۇيغۇرچە', Uyghur */,
49
+ 'ur' /* 'اردو', Urdu */,
50
+ 'yi' /* 'ייִדיש', Yiddish */
51
+ ];
52
+ // 'en-US' becomes ['en', '-us'] 'en' becomes ['en']
53
+ const localeRegex = /^([a-zA-Z]{2,3})([_\-a-zA-Z]{3,5})$/;
31
54
  const cleanLanguageCode = (str) => str.split('-')[0];
32
55
  const getNavigatorLanguage = () => cleanLanguageCode(navigator.language || navigator['userLanguage'] || '');
33
- const getStorageLanguage = () => { var _a; return cleanLanguageCode(((_a = window.BP_STORAGE) === null || _a === void 0 ? void 0 : _a.get(STORAGE_KEY)) || ''); };
56
+ const getStorageLanguage = () => cleanLanguageCode(window.BP_STORAGE.get(USER_LANG_STORAGE_KEY) || '');
57
+ const setStorageLanguage = (locale) => window.BP_STORAGE.set(USER_LANG_STORAGE_KEY, locale);
34
58
  // Desired precedence
35
59
  // 1- manual locale = 'browser' : browser lang
36
60
  // 2- manual locale is supported : manual lang
37
61
  // 3- storage lang is supported : storage lang
38
62
  // 4- browser lang is supported : browser lang
39
63
  // 5- default lang
40
- const getUserLocale = (manualLocale = 'browser') => {
64
+ const getUserLocale = (manualLocale = '') => {
41
65
  const browserLocale = getNavigatorLanguage();
42
66
  if (manualLocale === 'browser' && translations[browserLocale]) {
43
67
  return browserLocale;
@@ -53,3 +77,19 @@ const getUserLocale = (manualLocale = 'browser') => {
53
77
  return translations[browserLocale] ? browserLocale : DEFAULT_LOCALE;
54
78
  };
55
79
  exports.getUserLocale = getUserLocale;
80
+ const setUserLocale = (locale) => {
81
+ setStorageLanguage(locale);
82
+ };
83
+ exports.setUserLocale = setUserLocale;
84
+ const isRTLLocale = (locale) => {
85
+ if (!locale) {
86
+ return false;
87
+ }
88
+ locale = locale.toLowerCase();
89
+ const matches = localeRegex.exec(locale);
90
+ if (!matches || matches.length < 2) {
91
+ return false;
92
+ }
93
+ return rtlLocales.includes(matches[1]);
94
+ };
95
+ exports.isRTLLocale = isRTLLocale;
package/dist/typings.d.ts CHANGED
@@ -1,22 +1,16 @@
1
1
  /// <reference types="react" />
2
2
  import { RootStore } from './store';
3
+ import { BPStorage } from './utils/storage';
3
4
  declare global {
4
5
  interface Window {
5
6
  __BP_VISITOR_SOCKET_ID: string;
6
7
  __BP_VISITOR_ID: string;
7
8
  botpressWebChat: any;
8
9
  store: RootStore;
9
- BOT_API_PATH: string;
10
- API_PATH: string;
11
- BOTPRESS_VERSION: string;
12
- BOT_NAME: string;
13
- ROOT_PATH: string;
14
10
  BOT_ID: string;
15
- BP_BASE_PATH: string;
16
11
  SEND_USAGE_STATS: boolean;
17
- SHOW_POWERED_BY: boolean;
18
12
  USE_SESSION_STORAGE: boolean;
19
- BP_STORAGE: any;
13
+ BP_STORAGE: BPStorage;
20
14
  botpress: {
21
15
  [moduleName: string]: any;
22
16
  };
@@ -35,7 +29,6 @@ export declare namespace Renderer {
35
29
  noBubble?: boolean;
36
30
  keyboard?: any;
37
31
  eventId?: string;
38
- isHighlighted?: boolean;
39
32
  isLastGroup?: boolean;
40
33
  isLastOfGroup?: boolean;
41
34
  isBotMessage?: boolean;
@@ -147,76 +140,137 @@ export interface Config {
147
140
  messagingUrl: string;
148
141
  /** Id of your messaging client */
149
142
  clientId: string;
150
- botId?: string;
151
- externalAuthToken?: string;
152
- userId?: string;
153
- conversationId?: uuid;
154
- /** Allows to set a different user id for different windows (eg: studio, specific bot, etc) */
155
- userIdScope?: string;
156
- enableReset: boolean;
143
+ /**
144
+ * Url of the Media File Service where we fetch the bot info
145
+ * @default ''
146
+ */
147
+ mediaFileServiceUrl?: string;
148
+ /**
149
+ * Key used to encrypt data in the localStorage
150
+ * @default '''
151
+ */
152
+ encryptionKey?: string;
153
+ /**
154
+ * Provide a path to a stylesheet to customize the webchat
155
+ * @default '''
156
+ */
157
157
  stylesheet?: string;
158
- isEmulator?: boolean;
159
- extraStylesheet?: string;
160
- showConversationsButton: boolean;
161
- showUserName: boolean;
162
- showUserAvatar: boolean;
163
- showTimestamp: boolean;
164
- enableTranscriptDownload: boolean;
165
- enableConversationDeletion: boolean;
166
- enableArrowNavigation: boolean;
167
- closeOnEscape: boolean;
158
+ /**
159
+ * If false, will hide the conversation list pane
160
+ * @default true
161
+ */
162
+ showConversationsButton?: boolean;
163
+ /**
164
+ * If true, will display a timestamp under each messages
165
+ * @default false
166
+ */
167
+ showTimestamp?: boolean;
168
+ /**
169
+ * Allows the user to download the conversation history
170
+ * @default true
171
+ */
172
+ enableTranscriptDownload?: boolean;
173
+ /**
174
+ * Allows the user to delete its conversation history
175
+ * @default false
176
+ */
177
+ enableConversationDeletion?: boolean;
178
+ /**
179
+ * Close the webchat when pressing the Esc key
180
+ * @default true
181
+ */
182
+ closeOnEscape?: boolean;
183
+ /**
184
+ * Displays the bot name to the right of its avatar
185
+ * @default ''
186
+ */
168
187
  botName?: string;
188
+ /**
189
+ * Allows to set a custom composer placeholder
190
+ * @default 'Reply to {name}'
191
+ */
169
192
  composerPlaceholder?: string;
193
+ /**
194
+ * Allow to specify a custom URL for the bot's avatar
195
+ * @default '''
196
+ */
170
197
  avatarUrl?: string;
171
198
  /** Force the display language of the webchat (en, fr, ar, ru, etc..)
172
199
  * Defaults to the user's browser language if not set
173
200
  * Set to 'browser' to force use the browser's language
201
+ * @default 'browser'
174
202
  */
175
203
  locale?: 'browser' | string;
176
- /** Small description written under the bot's name */
177
- botConvoDescription?: string;
178
- /** Replace or insert components at specific locations */
179
- overrides?: Overrides;
180
- /** When true, the widget button is hidden */
181
- hideWidget: boolean;
182
- /** Disable the slide in / out animations of the webchat */
183
- disableAnimations: boolean;
184
- /** When true, sets ctrl+Enter as shortcut for reset session then send */
185
- enableResetSessionShortcut: boolean;
186
- /** When true, webchat tries to use native webspeech api (uses hosted mozilla and google voice services) */
187
- enableVoiceComposer: boolean;
188
- recentConversationLifetime: string;
189
- startNewConvoOnTimeout: boolean;
190
- /** Use sessionStorage instead of localStorage, which means the session expires when tab is closed */
191
- useSessionStorage: boolean;
204
+ /**
205
+ * Small description written under the bot's name
206
+ * @default ''
207
+ */
208
+ botConversationDescription?: string;
209
+ /**
210
+ * When true, the widget button to open the chat is hidden
211
+ * @default false
212
+ */
213
+ hideWidget?: boolean;
214
+ /**
215
+ * Disable the slide in / out animations of the webchat
216
+ * @default false
217
+ */
218
+ disableAnimations?: boolean;
219
+ /**
220
+ * When true, webchat displays a voice icon in the composer to send voice messages (must use Google Speech integration)
221
+ * @default false
222
+ */
223
+ enableVoiceComposer?: boolean;
224
+ /**
225
+ * Use sessionStorage instead of localStorage, which means the session expires when tab is closed
226
+ * @default false
227
+ */
228
+ useSessionStorage?: boolean;
229
+ /**
230
+ * Sends an event to the parent container with the width provided
231
+ * @default 360
232
+ */
192
233
  containerWidth?: string | number;
234
+ /**
235
+ * Sets the width of the webchat
236
+ * @default 360
237
+ */
193
238
  layoutWidth?: string | number;
194
- showPoweredBy: boolean;
195
- /** When enabled, sent messages are persisted to local storage (recall previous messages) */
196
- enablePersistHistory: boolean;
197
- /** Experimental: expose the store to the parent frame for more control on the webchat's behavior */
198
- exposeStore: boolean;
199
- /** Reference ensures that a specific value and its signature are valid */
200
- reference?: string;
201
- /** If true, Websocket is created when the Webchat is opened. Bot cannot be proactive. */
239
+ /**
240
+ * Show Powered By Botpress in the footer
241
+ * @default false
242
+ */
243
+ showPoweredBy?: boolean;
244
+ /**
245
+ * When enabled, sent messages are persisted to local storage (recall previous messages)
246
+ * @default true
247
+ */
248
+ enablePersistHistory?: boolean;
249
+ /**
250
+ * Experimental: expose the store to the parent frame for more control on the webchat's behavior
251
+ * @default false
252
+ */
253
+ exposeStore?: boolean;
254
+ /**
255
+ * If true, Websocket is created when the Webchat is opened. Bot cannot be proactive.
256
+ * @default false
257
+ */
202
258
  lazySocket?: boolean;
203
- /** If true, chat will no longer play the notification sound for new messages. */
259
+ /**
260
+ * If true, chat will no longer play the notification sound for new messages.
261
+ * @default false
262
+ */
204
263
  disableNotificationSound?: boolean;
205
- /** Refers to a specific webchat reference in parent window. Useful when using multiple chat window */
264
+ /**
265
+ * Refers to a specific webchat reference in parent window. Useful when using multiple chat window
266
+ * @default ''
267
+ */
206
268
  chatId?: string;
207
- /** CSS class to be applied to iframe */
269
+ /**
270
+ * CSS class to be applied to iframe
271
+ * @default '''
272
+ */
208
273
  className?: string;
209
- /** Key used to encrypt data in the localStorage */
210
- encryptionKey?: string;
211
- }
212
- export declare type OverridableComponents = 'below_conversation' | 'before_container' | 'composer';
213
- export interface Overrides {
214
- [componentToOverride: string]: [
215
- {
216
- module: string;
217
- component: string;
218
- }
219
- ];
220
274
  }
221
275
  export interface BotDetails {
222
276
  website?: string;
@@ -225,6 +279,7 @@ export interface BotDetails {
225
279
  privacyPolicy?: string;
226
280
  emailAddress?: string;
227
281
  avatarUrl?: string;
282
+ coverPictureUrl?: string;
228
283
  }
229
284
  export interface BotInfo {
230
285
  name: string;
@@ -236,6 +291,8 @@ export interface BotInfo {
236
291
  escapeHTML: boolean;
237
292
  };
238
293
  lazySocket: boolean;
294
+ extraStylesheet?: string;
295
+ disableNotificationSound?: boolean;
239
296
  }
240
297
  export declare type uuid = string;
241
298
  export interface Conversation {
@@ -298,13 +355,6 @@ export interface CustomAction {
298
355
  /** The event triggered when the action is clicked */
299
356
  onClick: (actionId: string, messageProps: any, event: React.MouseEvent) => void;
300
357
  }
301
- /** When set, this will wrap every messages displayed in the webchat */
302
- export interface MessageWrapper {
303
- /** The name of the module hosting the component */
304
- module: string;
305
- /** Name of the component exposed by the module */
306
- component: string;
307
- }
308
358
  export interface EventFeedback {
309
359
  messageId: uuid;
310
360
  feedback?: number;
@@ -0,0 +1,5 @@
1
+ export declare const initializeAnalytics: () => void;
2
+ export declare type MessageDirection = 'sent' | 'received';
3
+ export declare const trackMessage: (direction: MessageDirection) => void;
4
+ export declare type WebchatState = 'show' | 'hide' | 'toggle';
5
+ export declare const trackWebchatState: (state: WebchatState) => void;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.trackWebchatState = exports.trackMessage = exports.initializeAnalytics = void 0;
7
+ const react_ga_1 = __importDefault(require("react-ga"));
8
+ const initializeAnalytics = () => {
9
+ if (window.SEND_USAGE_STATS) {
10
+ try {
11
+ react_ga_1.default.initialize('UA-90044826-2');
12
+ react_ga_1.default.pageview(`${window.location.pathname}${window.location.search}`);
13
+ }
14
+ catch (err) {
15
+ console.error('Error initializing analytics', err);
16
+ }
17
+ }
18
+ };
19
+ exports.initializeAnalytics = initializeAnalytics;
20
+ const trackMessage = (direction) => {
21
+ if (window.SEND_USAGE_STATS) {
22
+ try {
23
+ react_ga_1.default.event({ category: 'Interactions', action: `message ${direction}` });
24
+ }
25
+ catch (_a) { }
26
+ }
27
+ };
28
+ exports.trackMessage = trackMessage;
29
+ const trackWebchatState = (state) => {
30
+ if (window.SEND_USAGE_STATS) {
31
+ try {
32
+ react_ga_1.default.event({ category: 'Display', action: state });
33
+ }
34
+ catch (_a) { }
35
+ }
36
+ };
37
+ exports.trackWebchatState = trackWebchatState;
@@ -0,0 +1,3 @@
1
+ export declare const isIE: boolean;
2
+ export declare const downloadFile: (name: string, blob: Blob) => void;
3
+ export declare const renderUnsafeHTML: (message: string | undefined, escaped: boolean) => string;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.renderUnsafeHTML = exports.downloadFile = exports.isIE = void 0;
7
+ const snarkdown_1 = __importDefault(require("snarkdown"));
8
+ exports.isIE = window.navigator.userAgent.match(/MSIE|Trident/) !== null;
9
+ const downloadFile = (name, blob) => {
10
+ const url = window.URL.createObjectURL(blob);
11
+ const link = document.createElement('a');
12
+ link.href = url;
13
+ link.setAttribute('download', name);
14
+ document.body.appendChild(link);
15
+ link.click();
16
+ document.body.removeChild(link);
17
+ window.URL.revokeObjectURL(url);
18
+ };
19
+ exports.downloadFile = downloadFile;
20
+ const renderUnsafeHTML = (message = '', escaped) => {
21
+ if (escaped) {
22
+ message = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
23
+ }
24
+ const html = (0, snarkdown_1.default)(message);
25
+ return html.replace(/<a href/gi, '<a target="_blank" href');
26
+ };
27
+ exports.renderUnsafeHTML = renderUnsafeHTML;
@@ -0,0 +1,16 @@
1
+ import { Config } from '../typings';
2
+ export declare class BPStorage {
3
+ private _config?;
4
+ private _storage;
5
+ constructor(config?: Config);
6
+ get config(): Config | undefined;
7
+ set config(config: Config | undefined);
8
+ private serialize;
9
+ private deserialize;
10
+ private getStorageKey;
11
+ private getDriver;
12
+ set<T>(key: string, value: T): void;
13
+ get<T = string>(key: string): T | undefined;
14
+ del(key: string): void;
15
+ }
16
+ export default BPStorage;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BPStorage = void 0;
7
+ const aes_1 = __importDefault(require("crypto-js/aes"));
8
+ const enc_utf8_1 = __importDefault(require("crypto-js/enc-utf8"));
9
+ const sha256_1 = __importDefault(require("crypto-js/sha256"));
10
+ const js_cookie_1 = __importDefault(require("js-cookie"));
11
+ class BPStorage {
12
+ constructor(config) {
13
+ this.serialize = (value) => {
14
+ var _a, _b;
15
+ if (value === null || value === undefined) {
16
+ throw new Error('[Storage] Cannot store null or undefined values');
17
+ }
18
+ try {
19
+ let str = '';
20
+ if (typeof value === 'string') {
21
+ str = value;
22
+ }
23
+ else {
24
+ str = JSON.stringify(value);
25
+ }
26
+ if ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.encryptionKey) === null || _b === void 0 ? void 0 : _b.length) {
27
+ str = aes_1.default.encrypt(str, this.config.encryptionKey).toString();
28
+ }
29
+ return str;
30
+ }
31
+ catch (_c) {
32
+ console.error('[Storage] Error parsing value', value);
33
+ return '';
34
+ }
35
+ };
36
+ this.deserialize = (strValue) => {
37
+ var _a, _b;
38
+ if (strValue === null || strValue === undefined) {
39
+ return undefined;
40
+ }
41
+ try {
42
+ if ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.encryptionKey) === null || _b === void 0 ? void 0 : _b.length) {
43
+ strValue = aes_1.default.decrypt(strValue, this.config.encryptionKey).toString(enc_utf8_1.default);
44
+ }
45
+ return JSON.parse(strValue);
46
+ }
47
+ catch (_c) {
48
+ return undefined;
49
+ }
50
+ };
51
+ this.getStorageKey = (key) => {
52
+ var _a, _b, _c;
53
+ const rawKey = `bp-chat-${key}`;
54
+ if ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.encryptionKey) === null || _b === void 0 ? void 0 : _b.length) {
55
+ return `${rawKey}-${(0, sha256_1.default)(`${this.config.clientId}-${this.config.encryptionKey}`).toString()}`;
56
+ }
57
+ else {
58
+ return `${rawKey}-${(_c = this.config) === null || _c === void 0 ? void 0 : _c.clientId}`;
59
+ }
60
+ };
61
+ this.getDriver = () => {
62
+ var _a;
63
+ if (this._storage) {
64
+ return this._storage;
65
+ }
66
+ try {
67
+ const storage = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.useSessionStorage) === true && typeof sessionStorage !== 'undefined' ? sessionStorage : localStorage;
68
+ const tempKey = '__storage_test__';
69
+ storage.setItem(tempKey, tempKey);
70
+ storage.removeItem(tempKey);
71
+ return (this._storage = storage);
72
+ }
73
+ catch (e) {
74
+ return (this._storage = 'cookie');
75
+ }
76
+ };
77
+ if (config) {
78
+ this._config = config;
79
+ }
80
+ }
81
+ get config() {
82
+ return this._config;
83
+ }
84
+ set config(config) {
85
+ this._config = config;
86
+ }
87
+ set(key, value) {
88
+ if (!this.config) {
89
+ return;
90
+ }
91
+ try {
92
+ const driver = this.getDriver();
93
+ driver !== 'cookie'
94
+ ? driver.setItem(this.getStorageKey(key), this.serialize(value))
95
+ : js_cookie_1.default.set(this.getStorageKey(key), this.serialize(value));
96
+ }
97
+ catch (err) {
98
+ console.error('Error while setting data into storage.', err.message);
99
+ }
100
+ }
101
+ get(key) {
102
+ if (!this.config) {
103
+ return;
104
+ }
105
+ try {
106
+ const driver = this.getDriver();
107
+ return driver !== 'cookie'
108
+ ? this.deserialize(driver.getItem(this.getStorageKey(key)))
109
+ : this.deserialize(js_cookie_1.default.get(this.getStorageKey(key)));
110
+ }
111
+ catch (err) {
112
+ console.error('Error while getting data from storage.', err.message);
113
+ }
114
+ }
115
+ del(key) {
116
+ if (!this.config) {
117
+ return;
118
+ }
119
+ try {
120
+ const driver = this.getDriver();
121
+ driver !== 'cookie' ? driver.removeItem(this.getStorageKey(key)) : js_cookie_1.default.remove(this.getStorageKey(key));
122
+ }
123
+ catch (err) {
124
+ console.error('Error while deleting data from storage.', err.message);
125
+ }
126
+ }
127
+ }
128
+ exports.BPStorage = BPStorage;
129
+ exports.default = BPStorage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botpress/webchat",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "source": "src/index.tsx",
@@ -15,6 +15,7 @@
15
15
  ],
16
16
  "devDependencies": {
17
17
  "@types/crypto-js": "^4.1.1",
18
+ "@types/js-cookie": "^3.0.1",
18
19
  "@types/lodash": "^4.14.178",
19
20
  "@types/mime": "^2.0.3",
20
21
  "@types/node": "^16.11.13",
@@ -25,7 +26,7 @@
25
26
  },
26
27
  "dependencies": {
27
28
  "@blueprintjs/core": "^3.23.1",
28
- "@botpress/messaging-components": "0.2.0",
29
+ "@botpress/messaging-components": "0.3.0",
29
30
  "@botpress/messaging-socket": "1.1.0",
30
31
  "@formatjs/intl-pluralrules": "^4.1.6",
31
32
  "@formatjs/intl-utils": "^3.8.4",
@@ -34,11 +35,11 @@
34
35
  "classnames": "^2.3.1",
35
36
  "crypto-js": "^4.1.1",
36
37
  "date-fns": "^1.30.1",
38
+ "js-cookie": "^3.0.1",
37
39
  "lodash": "^4.17.21",
38
40
  "mime": "^3.0.0",
39
41
  "mobx": "5.15.7",
40
42
  "mobx-react": "^6.2.1",
41
- "mobx-react-lite": "2.0.0",
42
43
  "query-string": "^7.1.0",
43
44
  "react": "^17.0.2",
44
45
  "react-dom": "^17.0.2",
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const showContextMenu: (e: React.MouseEvent<HTMLDivElement>, props: any) => void;
@@ -1,33 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.showContextMenu = void 0;
7
- const core_1 = require("@blueprintjs/core");
8
- const react_1 = __importDefault(require("react"));
9
- function MessageMenu(props) {
10
- return (react_1.default.createElement(core_1.Menu, null, props.customActions.map((action) => {
11
- return (react_1.default.createElement(core_1.MenuItem, { key: action.id, text: action.label,
12
- // TODO: undefined is supposed to be "this". Does that make sense??
13
- onClick: action.onClick.bind(undefined, action.id, props.element) }));
14
- })));
15
- }
16
- const showContextMenu = (e, props) => {
17
- const customActions = props.store.view.customActions;
18
- if (props.store.config.isEmulator) {
19
- customActions.push({
20
- id: 'actionDebug',
21
- label: 'Inspect in Debugger',
22
- onClick: (_actionId, props) => {
23
- props.store.loadEventInDebugger(props.incomingEventId, true);
24
- }
25
- });
26
- }
27
- if (customActions && props.incomingEventId) {
28
- e.preventDefault();
29
- const menu = react_1.default.createElement(MessageMenu, { element: props, customActions: customActions });
30
- core_1.ContextMenu.show(menu, { left: e.clientX, top: e.clientY });
31
- }
32
- };
33
- exports.showContextMenu = showContextMenu;
@@ -1,24 +0,0 @@
1
- import React from 'react';
2
- import { Overrides } from '../typings';
3
- declare class OverridableComponent extends React.Component<Props, State> {
4
- state: State;
5
- componentDidMount(): void;
6
- componentDidUpdate(prevProps: Props): void;
7
- componentDidCatch(error: any, info: any): void;
8
- loadComponents(): void;
9
- resolveComponents: () => {
10
- key: string;
11
- element: any;
12
- }[] | undefined;
13
- render(): any;
14
- }
15
- declare const _default: typeof OverridableComponent & import("mobx-react").IWrappedComponent<unknown>;
16
- export default _default;
17
- interface Props {
18
- name: string;
19
- overrides?: Overrides;
20
- original?: any;
21
- }
22
- interface State {
23
- components: any;
24
- }