@product7/feedback-sdk 1.3.4 → 1.3.5

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.
@@ -549,25 +549,81 @@
549
549
  );
550
550
  }
551
551
 
552
+ async getMessages(conversationId, options = {}) {
553
+ await this.api._ensureSession();
554
+
555
+ if (this.api.mock) {
556
+ await delay$1(200);
557
+ return {
558
+ status: true,
559
+ data: MOCK_MESSAGES$1[conversationId] || [],
560
+ meta: { total: 0, page: 1, limit: 50 },
561
+ };
562
+ }
563
+
564
+ const params = { ...options };
565
+ const endpoint = this.api._getEndpointWithParams(
566
+ `/widget/messenger/conversations/${conversationId}/messages`,
567
+ params
568
+ );
569
+ return this.api._makeRequest(endpoint, {
570
+ method: 'GET',
571
+ headers: { Authorization: `Bearer ${this.api.sessionToken}` },
572
+ });
573
+ }
574
+
552
575
  async identifyContact(data) {
553
- await this.api._ensureSession();
576
+ await this.api._ensureSession();
554
577
 
555
- if (this.api.mock) {
556
- return { status: true, data: { identified: true } };
578
+ if (this.api.mock) {
579
+ await delay$1(300);
580
+ return {
581
+ status: true,
582
+ data: {
583
+ contact_id: 'mock_contact_' + Date.now(),
584
+ email: data.email,
585
+ name: data.name || '',
586
+ is_new: true,
587
+ },
588
+ };
589
+ }
590
+
591
+ return this.api._makeRequest('/widget/messenger/identify', {
592
+ method: 'POST',
593
+ headers: {
594
+ 'Content-Type': 'application/json',
595
+ Authorization: `Bearer ${this.api.sessionToken}`,
596
+ },
597
+ body: JSON.stringify({
598
+ email: data.email,
599
+ name: data.name || '',
600
+ phone: data.phone || '',
601
+ company: data.company || '',
602
+ avatar_url: data.avatar_url || '',
603
+ metadata: data.metadata || {},
604
+ }),
605
+ });
557
606
  }
558
607
 
559
- return this.api._makeRequest('/widget/messenger/identify', {
560
- method: 'POST',
561
- headers: {
562
- 'Content-Type': 'application/json',
563
- Authorization: `Bearer ${this.api.sessionToken}`,
564
- },
565
- body: JSON.stringify({
566
- name: data.name,
567
- email: data.email,
568
- }),
569
- });
570
- }
608
+ async sendTypingIndicator(conversationId, isTyping) {
609
+ await this.api._ensureSession();
610
+
611
+ if (this.api.mock) {
612
+ return { status: true };
613
+ }
614
+
615
+ return this.api._makeRequest(
616
+ `/widget/messenger/conversations/${conversationId}/typing`,
617
+ {
618
+ method: 'POST',
619
+ headers: {
620
+ 'Content-Type': 'application/json',
621
+ Authorization: `Bearer ${this.api.sessionToken}`,
622
+ },
623
+ body: JSON.stringify({ is_typing: isTyping }),
624
+ }
625
+ );
626
+ }
571
627
  }
572
628
 
573
629
  class SDKError extends Error {
@@ -766,6 +822,10 @@
766
822
  base: 'https://staging.api.product7.io/api/v1',
767
823
  withWorkspace: (ws) => `https://${ws}.staging.api.product7.io/api/v1`,
768
824
  },
825
+ localstack: {
826
+ base: 'http://localhost:1323/api/v1',
827
+ withWorkspace: (ws) => `http://${ws}.localhost:1323/api/v1`,
828
+ },
769
829
  };
770
830
 
771
831
  const envConfig = ENV_URLS[this.env] || ENV_URLS.production;
@@ -2895,52 +2955,55 @@
2895
2955
  * MessengerState - State management for the Messenger widget
2896
2956
  */
2897
2957
  class MessengerState {
2898
- constructor(options = {}) {
2899
- this.currentView = 'home'; // 'home', 'messages', 'chat', 'help', 'changelog'
2900
- this.isOpen = false;
2901
- this.unreadCount = 0;
2902
- this.activeConversationId = null;
2903
-
2904
- // Conversations
2905
- this.conversations = [];
2906
- this.messages = {}; // { conversationId: [messages] }
2907
-
2908
- // Help articles
2909
- this.helpArticles = [];
2910
- this.helpSearchQuery = '';
2911
-
2912
- // Changelog
2913
- this.homeChangelogItems = [];
2914
- this.changelogItems = [];
2915
-
2916
- // Team info
2917
- this.teamName = options.teamName || 'Support';
2918
- this.teamAvatars = options.teamAvatars || [];
2919
- this.welcomeMessage = options.welcomeMessage || 'How can we help?';
2920
-
2921
- // User info
2922
- this.userContext = options.userContext || null;
2923
-
2924
- // Feature flags
2925
- this.enableHelp = options.enableHelp !== false;
2926
- this.enableChangelog = options.enableChangelog !== false;
2927
-
2928
- // Agent availability
2929
- this.agentsOnline = false;
2930
- this.onlineCount = 0;
2931
- this.responseTime = 'Usually replies within a few minutes';
2932
-
2933
- // Typing indicators
2934
- this.typingUsers = {}; // { conversationId: { userName, timestamp } }
2935
-
2936
- // Loading states
2937
- this.isLoading = false;
2938
- this.isLoadingMessages = false;
2939
-
2940
- // Listeners
2941
- this._listeners = new Set();
2942
- }
2943
-
2958
+ constructor(options = {}) {
2959
+ this.currentView = 'home';
2960
+ this.isOpen = false;
2961
+ this.unreadCount = 0;
2962
+ this.activeConversationId = null;
2963
+
2964
+ // Conversations
2965
+ this.conversations = [];
2966
+ this.messages = {};
2967
+
2968
+ // Help articles
2969
+ this.helpArticles = [];
2970
+ this.helpSearchQuery = '';
2971
+
2972
+ // Changelog
2973
+ this.homeChangelogItems = [];
2974
+ this.changelogItems = [];
2975
+
2976
+ // Team info
2977
+ this.teamName = options.teamName || 'Support';
2978
+ this.teamAvatars = options.teamAvatars || [];
2979
+ this.welcomeMessage = options.welcomeMessage || 'How can we help?';
2980
+
2981
+ // User info
2982
+ this.userContext = options.userContext || null;
2983
+
2984
+ // ADD THESE TWO PROPERTIES
2985
+ this.isIdentified = false; // Track if user has been identified
2986
+ this.pendingMessage = null; // { content, attachments } - for pre-chat flow
2987
+
2988
+ // Feature flags
2989
+ this.enableHelp = options.enableHelp !== false;
2990
+ this.enableChangelog = options.enableChangelog !== false;
2991
+
2992
+ // Agent availability
2993
+ this.agentsOnline = false;
2994
+ this.onlineCount = 0;
2995
+ this.responseTime = 'Usually replies within a few minutes';
2996
+
2997
+ // Typing indicators
2998
+ this.typingUsers = {};
2999
+
3000
+ // Loading states
3001
+ this.isLoading = false;
3002
+ this.isLoadingMessages = false;
3003
+
3004
+ // Listeners
3005
+ this._listeners = new Set();
3006
+ }
2944
3007
  /**
2945
3008
  * Subscribe to state changes
2946
3009
  */
@@ -5750,22 +5813,9 @@
5750
5813
 
5751
5814
  async _handleStartConversation(messageContent, pendingAttachments) {
5752
5815
  try {
5753
- const userContext = this.messengerState.userContext;
5754
- const isAuthenticated = userContext?.email && userContext?.name;
5755
-
5756
- if (isAuthenticated) {
5757
- try {
5758
- await this.apiService.identifyContact({
5759
- name: userContext.name,
5760
- email: userContext.email,
5761
- });
5762
- console.log('[MessengerWidget] User auto-identified for conversation');
5763
- } catch (error) {
5764
- if (error?.code !== 'ALREADY_IDENTIFIED') {
5765
- console.warn('[MessengerWidget] Auto-identification failed:', error);
5766
- }
5767
- }
5768
- } else {
5816
+ // Check if already identified
5817
+ if (!this.messengerState.isIdentified) {
5818
+ // Not identified - show pre-chat form
5769
5819
  this.messengerState.pendingMessage = {
5770
5820
  content: messageContent,
5771
5821
  attachments: pendingAttachments,
@@ -5774,6 +5824,7 @@
5774
5824
  return null;
5775
5825
  }
5776
5826
 
5827
+ // Already identified - proceed with conversation
5777
5828
  const openConversation = this.messengerState.conversations.find(
5778
5829
  (c) => c.status === 'open'
5779
5830
  );
@@ -5822,42 +5873,44 @@
5822
5873
  }
5823
5874
  }
5824
5875
 
5825
- async _handleIdentifyContact(contactData) {
5826
- try {
5827
- const response = await this.apiService.identifyContact({
5828
- name: contactData.name,
5829
- email: contactData.email,
5830
- });
5831
-
5832
- if (response.status) {
5833
- console.log('[MessengerWidget] Contact identified:', contactData.email);
5834
-
5835
- if (!this.messengerState.userContext) {
5836
- this.messengerState.userContext = {};
5837
- }
5838
- this.messengerState.userContext.name = contactData.name;
5839
- this.messengerState.userContext.email = contactData.email;
5876
+ async _handleIdentifyContact(contactData) {
5877
+ try {
5878
+ const response = await this.apiService.identifyContact({
5879
+ name: contactData.name,
5880
+ email: contactData.email,
5881
+ });
5840
5882
 
5841
- const pendingMessage = this.messengerState.pendingMessage;
5842
- if (pendingMessage) {
5843
- this.messengerState.pendingMessage = null;
5883
+ if (response.status) {
5884
+ console.log('[MessengerWidget] Contact identified:', response.data.contact_id);
5844
5885
 
5845
- await this.startNewConversation(
5846
- pendingMessage.content,
5847
- '',
5848
- pendingMessage.attachments
5849
- );
5850
- } else {
5851
- this.messengerState.setView('chat');
5852
- }
5886
+ // Update state
5887
+ if (!this.messengerState.userContext) {
5888
+ this.messengerState.userContext = {};
5889
+ }
5890
+ this.messengerState.userContext.name = contactData.name;
5891
+ this.messengerState.userContext.email = contactData.email;
5892
+ this.messengerState.isIdentified = true; // ADD THIS LINE
5893
+
5894
+ // Process pending message
5895
+ const pendingMessage = this.messengerState.pendingMessage;
5896
+ if (pendingMessage) {
5897
+ this.messengerState.pendingMessage = null;
5898
+ await this.startNewConversation(
5899
+ pendingMessage.content,
5900
+ '',
5901
+ pendingMessage.attachments
5902
+ );
5903
+ } else {
5904
+ this.messengerState.setView('chat');
5853
5905
  }
5854
-
5855
- return response;
5856
- } catch (error) {
5857
- console.error('[MessengerWidget] Failed to identify contact:', error);
5858
- throw error;
5859
5906
  }
5907
+
5908
+ return response;
5909
+ } catch (error) {
5910
+ console.error('[MessengerWidget] Failed to identify contact:', error);
5911
+ throw error;
5860
5912
  }
5913
+ }
5861
5914
 
5862
5915
  async _handleUploadFile(base64Data, filename) {
5863
5916
  try {