customer-chat-sdk 1.1.7 → 1.1.8

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.
@@ -17,6 +17,7 @@ export declare class IframeManager {
17
17
  private isOpen;
18
18
  private isCreated;
19
19
  private debug;
20
+ private messageHandler;
20
21
  constructor(config?: IframeOptions);
21
22
  /**
22
23
  * 初始化iframe(隐藏状态)
@@ -1 +1 @@
1
- {"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../src/core/IframeManager.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAA;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IACpD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAiB;gBAElB,MAAM,GAAE,aAAkB;IActC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;IACH,IAAI,IAAI,IAAI;IA2CZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAgBf;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAM7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiIpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8D1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwD3B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
1
+ {"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../src/core/IframeManager.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAA;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IACpD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,cAAc,CAA+C;gBAEzD,MAAM,GAAE,aAAkB;IActC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;IACH,IAAI,IAAI,IAAI;IA2CZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAyBf;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAM7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiIpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8D1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAwB5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwD3B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
@@ -609,6 +609,7 @@ class IframeManager {
609
609
  this.isOpen = false;
610
610
  this.isCreated = false;
611
611
  this.debug = false; // debug 模式标志
612
+ this.messageHandler = null; // 消息监听器引用,用于清理
612
613
  this.config = {
613
614
  src: '',
614
615
  mode: 'auto', // 默认自动检测设备类型
@@ -727,6 +728,14 @@ class IframeManager {
727
728
  */
728
729
  destroy() {
729
730
  this.hide();
731
+ // 移除消息监听器(防止内存泄漏)
732
+ if (this.messageHandler) {
733
+ window.removeEventListener('message', this.messageHandler);
734
+ this.messageHandler = null;
735
+ if (this.debug) {
736
+ console.log('Message listener removed');
737
+ }
738
+ }
730
739
  // 移除容器
731
740
  if (this.containerElement) {
732
741
  this.containerElement.remove();
@@ -1001,12 +1010,24 @@ class IframeManager {
1001
1010
  * 设置消息监听
1002
1011
  */
1003
1012
  setupMessageListener() {
1004
- window.addEventListener('message', (event) => {
1013
+ // 如果已存在监听器,先移除旧的(防止重复添加)
1014
+ if (this.messageHandler) {
1015
+ window.removeEventListener('message', this.messageHandler);
1016
+ if (this.debug) {
1017
+ console.log('Removed old message listener');
1018
+ }
1019
+ }
1020
+ // 创建新的消息处理器并保存引用
1021
+ this.messageHandler = (event) => {
1005
1022
  // 验证消息来源(可选的安全检查)
1006
1023
  if (!this.config.src || event.origin === new URL(this.config.src).origin) {
1007
1024
  this.handleIframeMessage(event.data);
1008
1025
  }
1009
- }, false);
1026
+ };
1027
+ window.addEventListener('message', this.messageHandler, false);
1028
+ if (this.debug) {
1029
+ console.log('Message listener setup completed');
1030
+ }
1010
1031
  }
1011
1032
  /**
1012
1033
  * 处理来自iframe的消息
@@ -20792,6 +20813,7 @@ class CustomerServiceSDK {
20792
20813
  this.isInitialized = false;
20793
20814
  this.initResult = null; // 保存初始化结果
20794
20815
  this.debug = false; // debug 模式标志
20816
+ this.lastIconConfig = null; // 保存上一次的图标配置
20795
20817
  }
20796
20818
  /**
20797
20819
  * 初始化 SDK
@@ -20816,12 +20838,13 @@ class CustomerServiceSDK {
20816
20838
  if (this.debug) {
20817
20839
  console.log('Force reinitializing SDK...');
20818
20840
  }
20819
- // 清理旧的 iframe 和截图管理器,但保留图标管理器(保持图标位置等状态)
20841
+ // 清理旧的 iframe 和截图管理器
20820
20842
  this.iframeManager?.destroy();
20821
20843
  this.screenshotManager?.destroy();
20822
20844
  this.iframeManager = null;
20823
20845
  this.screenshotManager = null;
20824
- // 重置初始化标志,但保留图标管理器
20846
+ // 注意:图标管理器暂时保留,稍后检查配置是否变化再决定是否重新创建
20847
+ // 重置初始化标志
20825
20848
  this.isInitialized = false;
20826
20849
  }
20827
20850
  this.config = config;
@@ -20842,11 +20865,46 @@ class CustomerServiceSDK {
20842
20865
  agent: config.agent,
20843
20866
  timestamp: Date.now()
20844
20867
  };
20845
- // 创建悬浮图标管理器(支持自定义位置和传送目标)
20846
- const iconPosition = options?.iconPosition || undefined;
20847
- const iconTarget = options?.target || undefined;
20848
- this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20849
- await this.iconManager.show();
20868
+ // 处理图标管理器(优化:如果配置没变化,保留图标避免闪烁)
20869
+ // 如果 options 未提供,使用之前保存的配置(避免更新 token 时图标闪烁)
20870
+ const iconPosition = options?.iconPosition !== undefined
20871
+ ? options.iconPosition
20872
+ : (this.lastIconConfig?.position || undefined);
20873
+ const iconTarget = options?.target !== undefined
20874
+ ? options.target
20875
+ : (this.lastIconConfig?.target || undefined);
20876
+ // 检查图标配置是否变化
20877
+ const iconConfigChanged = this.isIconConfigChanged(iconPosition, iconTarget);
20878
+ if (iconConfigChanged) {
20879
+ // 配置变化了,需要重新创建图标管理器
20880
+ if (this.iconManager) {
20881
+ this.iconManager.hide();
20882
+ if (this.debug) {
20883
+ console.log('Icon config changed, recreating icon manager');
20884
+ }
20885
+ }
20886
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20887
+ await this.iconManager.show();
20888
+ // 保存新的配置
20889
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20890
+ }
20891
+ else {
20892
+ // 配置没变化,保留图标管理器(避免闪烁)
20893
+ if (!this.iconManager) {
20894
+ // 如果不存在,创建新的
20895
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20896
+ await this.iconManager.show();
20897
+ }
20898
+ else {
20899
+ // 已存在,确保显示(可能被隐藏了)
20900
+ await this.iconManager.show();
20901
+ if (this.debug) {
20902
+ console.log('Icon config unchanged, keeping existing icon manager');
20903
+ }
20904
+ }
20905
+ // 更新配置记录
20906
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20907
+ }
20850
20908
  // 创建iframe管理器(自动检测设备类型)
20851
20909
  this.iframeManager = new IframeManager({
20852
20910
  src: iframeUrl,
@@ -21094,6 +21152,7 @@ class CustomerServiceSDK {
21094
21152
  this.screenshotManager = null;
21095
21153
  this.config = null;
21096
21154
  this.initResult = null;
21155
+ this.lastIconConfig = null;
21097
21156
  this.isInitialized = false;
21098
21157
  if (this.debug) {
21099
21158
  console.log('CustomerSDK destroyed');
@@ -21138,6 +21197,36 @@ class CustomerServiceSDK {
21138
21197
  return fallbackId;
21139
21198
  }
21140
21199
  }
21200
+ /**
21201
+ * 检查图标配置是否变化
21202
+ */
21203
+ isIconConfigChanged(newPosition, newTarget) {
21204
+ // 如果没有保存的配置,说明是首次初始化,需要创建
21205
+ if (!this.lastIconConfig) {
21206
+ return true;
21207
+ }
21208
+ // 比较位置配置
21209
+ const positionChanged = JSON.stringify(this.lastIconConfig.position) !== JSON.stringify(newPosition);
21210
+ // 比较 target 配置
21211
+ const oldTarget = this.lastIconConfig.target;
21212
+ let targetChanged = false;
21213
+ if (oldTarget !== newTarget) {
21214
+ // 如果引用不同,进一步检查
21215
+ if (typeof oldTarget === 'string' && typeof newTarget === 'string') {
21216
+ // 都是字符串,比较值
21217
+ targetChanged = oldTarget !== newTarget;
21218
+ }
21219
+ else if (oldTarget instanceof HTMLElement && newTarget instanceof HTMLElement) {
21220
+ // 都是 HTMLElement,比较引用(引用不同就是变化了)
21221
+ targetChanged = true;
21222
+ }
21223
+ else {
21224
+ // 类型不同,肯定是变化了
21225
+ targetChanged = true;
21226
+ }
21227
+ }
21228
+ return positionChanged || targetChanged;
21229
+ }
21141
21230
  /**
21142
21231
  * 构建iframe URL(带用户参数和设备ID)
21143
21232
  */
@@ -605,6 +605,7 @@ class IframeManager {
605
605
  this.isOpen = false;
606
606
  this.isCreated = false;
607
607
  this.debug = false; // debug 模式标志
608
+ this.messageHandler = null; // 消息监听器引用,用于清理
608
609
  this.config = {
609
610
  src: '',
610
611
  mode: 'auto', // 默认自动检测设备类型
@@ -723,6 +724,14 @@ class IframeManager {
723
724
  */
724
725
  destroy() {
725
726
  this.hide();
727
+ // 移除消息监听器(防止内存泄漏)
728
+ if (this.messageHandler) {
729
+ window.removeEventListener('message', this.messageHandler);
730
+ this.messageHandler = null;
731
+ if (this.debug) {
732
+ console.log('Message listener removed');
733
+ }
734
+ }
726
735
  // 移除容器
727
736
  if (this.containerElement) {
728
737
  this.containerElement.remove();
@@ -997,12 +1006,24 @@ class IframeManager {
997
1006
  * 设置消息监听
998
1007
  */
999
1008
  setupMessageListener() {
1000
- window.addEventListener('message', (event) => {
1009
+ // 如果已存在监听器,先移除旧的(防止重复添加)
1010
+ if (this.messageHandler) {
1011
+ window.removeEventListener('message', this.messageHandler);
1012
+ if (this.debug) {
1013
+ console.log('Removed old message listener');
1014
+ }
1015
+ }
1016
+ // 创建新的消息处理器并保存引用
1017
+ this.messageHandler = (event) => {
1001
1018
  // 验证消息来源(可选的安全检查)
1002
1019
  if (!this.config.src || event.origin === new URL(this.config.src).origin) {
1003
1020
  this.handleIframeMessage(event.data);
1004
1021
  }
1005
- }, false);
1022
+ };
1023
+ window.addEventListener('message', this.messageHandler, false);
1024
+ if (this.debug) {
1025
+ console.log('Message listener setup completed');
1026
+ }
1006
1027
  }
1007
1028
  /**
1008
1029
  * 处理来自iframe的消息
@@ -20788,6 +20809,7 @@ class CustomerServiceSDK {
20788
20809
  this.isInitialized = false;
20789
20810
  this.initResult = null; // 保存初始化结果
20790
20811
  this.debug = false; // debug 模式标志
20812
+ this.lastIconConfig = null; // 保存上一次的图标配置
20791
20813
  }
20792
20814
  /**
20793
20815
  * 初始化 SDK
@@ -20812,12 +20834,13 @@ class CustomerServiceSDK {
20812
20834
  if (this.debug) {
20813
20835
  console.log('Force reinitializing SDK...');
20814
20836
  }
20815
- // 清理旧的 iframe 和截图管理器,但保留图标管理器(保持图标位置等状态)
20837
+ // 清理旧的 iframe 和截图管理器
20816
20838
  this.iframeManager?.destroy();
20817
20839
  this.screenshotManager?.destroy();
20818
20840
  this.iframeManager = null;
20819
20841
  this.screenshotManager = null;
20820
- // 重置初始化标志,但保留图标管理器
20842
+ // 注意:图标管理器暂时保留,稍后检查配置是否变化再决定是否重新创建
20843
+ // 重置初始化标志
20821
20844
  this.isInitialized = false;
20822
20845
  }
20823
20846
  this.config = config;
@@ -20838,11 +20861,46 @@ class CustomerServiceSDK {
20838
20861
  agent: config.agent,
20839
20862
  timestamp: Date.now()
20840
20863
  };
20841
- // 创建悬浮图标管理器(支持自定义位置和传送目标)
20842
- const iconPosition = options?.iconPosition || undefined;
20843
- const iconTarget = options?.target || undefined;
20844
- this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20845
- await this.iconManager.show();
20864
+ // 处理图标管理器(优化:如果配置没变化,保留图标避免闪烁)
20865
+ // 如果 options 未提供,使用之前保存的配置(避免更新 token 时图标闪烁)
20866
+ const iconPosition = options?.iconPosition !== undefined
20867
+ ? options.iconPosition
20868
+ : (this.lastIconConfig?.position || undefined);
20869
+ const iconTarget = options?.target !== undefined
20870
+ ? options.target
20871
+ : (this.lastIconConfig?.target || undefined);
20872
+ // 检查图标配置是否变化
20873
+ const iconConfigChanged = this.isIconConfigChanged(iconPosition, iconTarget);
20874
+ if (iconConfigChanged) {
20875
+ // 配置变化了,需要重新创建图标管理器
20876
+ if (this.iconManager) {
20877
+ this.iconManager.hide();
20878
+ if (this.debug) {
20879
+ console.log('Icon config changed, recreating icon manager');
20880
+ }
20881
+ }
20882
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20883
+ await this.iconManager.show();
20884
+ // 保存新的配置
20885
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20886
+ }
20887
+ else {
20888
+ // 配置没变化,保留图标管理器(避免闪烁)
20889
+ if (!this.iconManager) {
20890
+ // 如果不存在,创建新的
20891
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20892
+ await this.iconManager.show();
20893
+ }
20894
+ else {
20895
+ // 已存在,确保显示(可能被隐藏了)
20896
+ await this.iconManager.show();
20897
+ if (this.debug) {
20898
+ console.log('Icon config unchanged, keeping existing icon manager');
20899
+ }
20900
+ }
20901
+ // 更新配置记录
20902
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20903
+ }
20846
20904
  // 创建iframe管理器(自动检测设备类型)
20847
20905
  this.iframeManager = new IframeManager({
20848
20906
  src: iframeUrl,
@@ -21090,6 +21148,7 @@ class CustomerServiceSDK {
21090
21148
  this.screenshotManager = null;
21091
21149
  this.config = null;
21092
21150
  this.initResult = null;
21151
+ this.lastIconConfig = null;
21093
21152
  this.isInitialized = false;
21094
21153
  if (this.debug) {
21095
21154
  console.log('CustomerSDK destroyed');
@@ -21134,6 +21193,36 @@ class CustomerServiceSDK {
21134
21193
  return fallbackId;
21135
21194
  }
21136
21195
  }
21196
+ /**
21197
+ * 检查图标配置是否变化
21198
+ */
21199
+ isIconConfigChanged(newPosition, newTarget) {
21200
+ // 如果没有保存的配置,说明是首次初始化,需要创建
21201
+ if (!this.lastIconConfig) {
21202
+ return true;
21203
+ }
21204
+ // 比较位置配置
21205
+ const positionChanged = JSON.stringify(this.lastIconConfig.position) !== JSON.stringify(newPosition);
21206
+ // 比较 target 配置
21207
+ const oldTarget = this.lastIconConfig.target;
21208
+ let targetChanged = false;
21209
+ if (oldTarget !== newTarget) {
21210
+ // 如果引用不同,进一步检查
21211
+ if (typeof oldTarget === 'string' && typeof newTarget === 'string') {
21212
+ // 都是字符串,比较值
21213
+ targetChanged = oldTarget !== newTarget;
21214
+ }
21215
+ else if (oldTarget instanceof HTMLElement && newTarget instanceof HTMLElement) {
21216
+ // 都是 HTMLElement,比较引用(引用不同就是变化了)
21217
+ targetChanged = true;
21218
+ }
21219
+ else {
21220
+ // 类型不同,肯定是变化了
21221
+ targetChanged = true;
21222
+ }
21223
+ }
21224
+ return positionChanged || targetChanged;
21225
+ }
21137
21226
  /**
21138
21227
  * 构建iframe URL(带用户参数和设备ID)
21139
21228
  */