@capillarytech/creatives-library 8.0.138 → 8.0.139-alpha.1

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.138",
4
+ "version": "8.0.139-alpha.1",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -143,7 +143,7 @@ function CapImageUpload(props) {
143
143
 
144
144
  const capUploaderCustomRequest = useCallback((uploadData) => {
145
145
  uploadImages(undefined, {files: [uploadData.file]});
146
- }, []);
146
+ }, [uploadImages]);
147
147
 
148
148
  const setDrawerVisibility = useCallback((drawervisibleFlag) => updateDrawerRequirement(drawervisibleFlag), [isDrawerRequired]);
149
149
 
@@ -57,7 +57,7 @@
57
57
  }
58
58
  img {
59
59
  object-fit: cover;
60
- max-height: 150px;
60
+ max-height: 9.375rem;
61
61
  max-width: 18.75rem;
62
62
  }
63
63
  }
@@ -106,7 +106,7 @@
106
106
  .sms-text {
107
107
  img {
108
108
  display: block;
109
- max-width: 100%;
109
+ // max-width: 100%;
110
110
  object-fit: cover;
111
111
  }
112
112
  }
@@ -61,6 +61,22 @@ const CAROUSEL_INITIAL_DATA = {
61
61
  // Maximum number of carousel cards allowed
62
62
  const MAX_CAROUSEL_ALLOWED = 10;
63
63
 
64
+ // Helper function to find selected deep link with fallback to base URL
65
+ const findSelectedDeepLink = (links, value) => {
66
+ if (!links || !value) return undefined;
67
+
68
+ // Try to find exact match first
69
+ let selectedDeepLink = links.find((link) => link?.value === value);
70
+
71
+ // If no exact match and value contains query parameters, try base URL match
72
+ if (!selectedDeepLink && value?.includes('?')) {
73
+ const baseDeepLinkValue = value.split('?')[0];
74
+ selectedDeepLink = links.find((link) => link?.value === baseDeepLinkValue);
75
+ }
76
+
77
+ return selectedDeepLink;
78
+ };
79
+
64
80
  const MediaUploaders = ({
65
81
  mediaType,
66
82
  activeTab,
@@ -93,6 +109,16 @@ const MediaUploaders = ({
93
109
  // Track re-upload mode to prevent automatic restoration during re-upload
94
110
  const [isReUploading, setIsReUploading] = useState(false);
95
111
 
112
+ // Track which card is currently uploading to handle completion properly
113
+ const [uploadingCardIndex, setUploadingCardIndex] = useState(null);
114
+
115
+ // Track upload ID to prevent processing stale Redux data
116
+ const [currentUploadId, setCurrentUploadId] = useState(null);
117
+ const uploadIdRef = useRef(0); // Counter for generating unique upload IDs
118
+
119
+ // Track previous upload data to detect when a new upload completes
120
+ const previousUploadDataRef = useRef(null);
121
+
96
122
  // Track previous media type to handle transitions
97
123
  const previousMediaTypeRef = useRef(mediaType);
98
124
 
@@ -109,12 +135,25 @@ const MediaUploaders = ({
109
135
  }
110
136
  }, [activeTab, onCarouselDataChange]);
111
137
 
138
+ // Move updateCarouselCard to top level so useEffect can access it
139
+ const updateCarouselCard = useCallback((index, fields) => {
140
+ const currentData = getCurrentCarouselData();
141
+ setCurrentCarouselData(currentData.map((card, i) => (
142
+ i === index ? { ...card, ...fields } : card
143
+ )));
144
+ }, [getCurrentCarouselData, setCurrentCarouselData]);
145
+
112
146
  // Clear previous media data when switching media types
113
147
  useEffect(() => {
114
148
  // Clear carousel data when switching to non-carousel media types
115
149
  if (mediaType !== CAROUSEL) {
116
150
  setCurrentCarouselData([]);
117
151
  setCarouselActiveTabIndex(0);
152
+
153
+ // Reset carousel upload tracking
154
+ setUploadingCardIndex(null);
155
+ setCurrentUploadId(null);
156
+ previousUploadDataRef.current = null;
118
157
  }
119
158
 
120
159
  // Clear image data when switching away from IMAGE media type
@@ -139,7 +178,14 @@ const MediaUploaders = ({
139
178
  useEffect(() => {
140
179
  // Reset active tab index when switching platforms
141
180
  setCarouselActiveTabIndex(0);
142
- }, [activeTab]);
181
+
182
+ // Reset upload tracking when switching platforms to prevent cross-platform conflicts
183
+ if (mediaType === CAROUSEL) {
184
+ setUploadingCardIndex(null);
185
+ setCurrentUploadId(null);
186
+ previousUploadDataRef.current = null;
187
+ }
188
+ }, [activeTab, mediaType]);
143
189
 
144
190
  // Initialize carousel data if empty
145
191
  useEffect(() => {
@@ -148,37 +194,8 @@ const MediaUploaders = ({
148
194
  }
149
195
  }, [mediaType, carouselData, activeTab, setCurrentCarouselData]);
150
196
 
151
- // Listen for upload success and update carousel data
152
- useEffect(() => {
153
- // Skip automatic updates during re-upload mode
154
- if (isReUploading) {
155
- return;
156
- }
157
-
158
- if (mediaType === CAROUSEL && imageData) {
159
- const platformIndex = activeTab === ANDROID ? 0 : 1;
160
- const uploadedAssetData = imageData[`uploadedAssetData${platformIndex}`];
161
-
162
- // Only update if there's new upload data and it's different from current carousel data
163
- if (uploadedAssetData && uploadedAssetData.metaInfo && uploadedAssetData.metaInfo.secure_file_path) {
164
- const currentData = getCurrentCarouselData();
165
- if (currentData?.length > carouselActiveTabIndex) {
166
- const currentCard = currentData[carouselActiveTabIndex];
167
- const newImageUrl = uploadedAssetData.metaInfo.secure_file_path;
168
-
169
- // Only update if the image URL is different from the current one and not empty
170
- if (currentCard?.imageUrl !== newImageUrl && newImageUrl !== '') {
171
- const updatedData = [...currentData];
172
- updatedData[carouselActiveTabIndex] = {
173
- ...updatedData[carouselActiveTabIndex],
174
- imageUrl: newImageUrl,
175
- };
176
- setCurrentCarouselData(updatedData);
177
- }
178
- }
179
- }
180
- }
181
- }, [imageData, mediaType, activeTab, carouselActiveTabIndex, getCurrentCarouselData, setCurrentCarouselData, isReUploading]);
197
+ // Note: Carousel images use standard platform indices (0/1) and are handled
198
+ // by the updateImageSrc callback with CAROUSEL mediaType for proper separation
182
199
 
183
200
  const renderImageComponent = useCallback(() => {
184
201
  let imageSource = '';
@@ -363,46 +380,40 @@ const MediaUploaders = ({
363
380
  }
364
381
  };
365
382
 
366
- const updateCarouselCard = (index, fields) => {
367
- const currentData = getCurrentCarouselData();
368
- setCurrentCarouselData(currentData.map((card, i) => (
369
- i === index ? { ...card, ...fields } : card
370
- )));
371
- // Don't clear assets for carousel cards since they store data in component state, not Redux
372
- // Only clear assets for non-carousel media types
373
- };
383
+ // updateCarouselCard moved to top level to be accessible by useEffect
374
384
 
375
- const handleCarouselImageChange = (image) => {
376
- updateCarouselCard(parseInt(carouselActiveTabIndex, 10), { imageUrl: image });
385
+ const handleCarouselImageChange = (image, cardIndex) => {
386
+ // Update the specific card that uploaded the image, not the active card
387
+ updateCarouselCard(cardIndex, { imageUrl: image });
377
388
  };
378
389
 
379
- // Carousel-specific re-upload handler that clears both Redux and component state
380
- const handleCarouselImageReUpload = () => {
390
+ // Carousel-specific re-upload handler that clears both Redux and component state for specific card
391
+ const handleCarouselImageReUpload = (cardIndex) => {
381
392
  // Set re-upload mode to prevent automatic restoration
382
393
  setIsReUploading(true);
383
394
 
384
395
  // Clear Redux state (same as updateOnMpushImageReUpload)
385
396
  updateOnMpushImageReUpload();
386
397
 
387
- // Clear Redux uploadedAssetData to prevent automatic restoration
398
+ // Clear Redux uploadedAssetData to prevent automatic restoration using standard platform index
388
399
  const platformIndex = activeTab === ANDROID ? 0 : 1;
389
400
  mobilePushActions.clearAsset(platformIndex);
390
401
 
391
- // Clear carousel component state for the current card
402
+ // Clear carousel component state for the specific card
392
403
  const currentData = getCurrentCarouselData();
393
- if (currentData?.length > carouselActiveTabIndex) {
404
+ if (currentData?.length > cardIndex) {
394
405
  const updatedData = [...currentData];
395
- updatedData[carouselActiveTabIndex] = {
396
- ...updatedData[carouselActiveTabIndex],
406
+ updatedData[cardIndex] = {
407
+ ...updatedData[cardIndex],
397
408
  imageUrl: '',
398
409
  };
399
410
  setCurrentCarouselData(updatedData);
400
411
  }
401
412
 
402
- // Reset re-upload mode after a longer delay to allow for upload completion
413
+ // Reset re-upload mode after a delay
403
414
  setTimeout(() => {
404
415
  setIsReUploading(false);
405
- }, 3000); // Increased from 1000ms to 3000ms
416
+ }, 100);
406
417
  };
407
418
 
408
419
  // Action link handlers for carousel cards
@@ -467,6 +478,17 @@ const MediaUploaders = ({
467
478
  // Each carousel card maintains its own imageUrl
468
479
  const imageSource = card?.imageUrl || '';
469
480
 
481
+ // Custom upload function that tracks which card is uploading
482
+ const handleCarouselUpload = (file, assetType, fileParams, index) => {
483
+ // Generate unique upload ID to track this specific upload
484
+ uploadIdRef.current += 1;
485
+ const uploadId = uploadIdRef.current;
486
+
487
+ setUploadingCardIndex(cardIndex);
488
+ setCurrentUploadId(uploadId);
489
+ return uploadMpushAsset(file, assetType, fileParams, index);
490
+ };
491
+
470
492
  return (
471
493
  <CapImageUpload
472
494
  style={{ paddingTop: "20px" }}
@@ -474,22 +496,27 @@ const MediaUploaders = ({
474
496
  imgSize={MPUSH_IMG_SIZE}
475
497
  imgWidth={MPUSH_IMG_MAX_WIDTH}
476
498
  imgHeight={MPUSH_IMG_MAX_HEIGHT}
477
- uploadAsset={uploadMpushAsset}
499
+ uploadAsset={handleCarouselUpload}
478
500
  isFullMode={isFullMode}
479
501
  imageSrc={imageSource}
480
502
  updateImageSrc={(src) => {
481
- // Update only this specific carousel card's image
482
- handleCarouselImageChange(src);
503
+ // For gallery uploads (direct URL), update immediately
504
+ if (src && (src.includes('http') || src.includes('https'))) {
505
+ handleCarouselImageChange(src, cardIndex);
506
+ }
507
+
508
+ // Always call setUpdateMpushImageSrc for Redux state management
509
+ setUpdateMpushImageSrc(src, activeTab === ANDROID ? 0 : 1, CAROUSEL);
483
510
  }}
484
- updateOnReUpload={handleCarouselImageReUpload}
511
+ updateOnReUpload={() => handleCarouselImageReUpload(cardIndex)}
485
512
  index={activeTab === ANDROID ? 0 : 1}
486
513
  className="cap-custom-image-upload"
487
514
  key={`carousel-image-${activeTab}-${cardIndex}`}
488
- imageData={{}} // Empty object for carousel images since they're stored in component state
515
+ imageData={imageData}
489
516
  channel={MOBILE_PUSH_CHANNEL}
490
517
  showReUploadButton
491
518
  errorMessage={formatMessage(messages.imageErrorMessage)}
492
- disableAutoRestore // Disable automatic restoration for carousel images
519
+ disableAutoRestore // Disable automatic restoration to prevent all cards from showing the same image
493
520
  />
494
521
  );
495
522
  };
@@ -572,15 +599,15 @@ const MediaUploaders = ({
572
599
  options={(() => {
573
600
  const options = [...(deepLink || [])];
574
601
  // If the current value is not in the options, add it
575
- if (button.deepLinkValue && !options.find(opt => opt.value === button.deepLinkValue)) {
602
+ if (button?.deepLinkValue && !options.find(opt => opt.value === button?.deepLinkValue)) {
576
603
  options.push({
577
- value: button.deepLinkValue,
578
- label: button.deepLinkValue,
604
+ value: button?.deepLinkValue,
605
+ label: button?.deepLinkValue,
579
606
  });
580
607
  }
581
608
  return options;
582
609
  })()}
583
- value={button.deepLinkValue}
610
+ value={button?.deepLinkValue}
584
611
  onChange={(value) => handleCarouselDeepLinkChange(cardIndex, value)}
585
612
  key={`mobile-push-deep-link-type-${activeTab}-${cardIndex}`}
586
613
  placeholder={formatMessage(messages.selectDeepLink)}
@@ -616,12 +643,7 @@ const MediaUploaders = ({
616
643
  </CapRow>
617
644
  )}
618
645
  {button?.linkType === DEEP_LINK && button?.deepLinkValue && button?.actionOnClick && (() => {
619
- // Try to find exact match first, then try match without query parameters
620
- let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
621
- if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
622
- const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
623
- selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
624
- }
646
+ const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
625
647
  const deepLinkKeysFromSelection = selectedDeepLink?.keys;
626
648
  let deepLinkKeysFromSelectionArray = [];
627
649
  if (Array.isArray(deepLinkKeysFromSelection)) {
@@ -638,12 +660,7 @@ const MediaUploaders = ({
638
660
  </CapHeading>
639
661
  <CapLabel type="label2" className="deep-link-keys-value">
640
662
  {(() => {
641
- // Try to find exact match first, then try match without query parameters
642
- let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
643
- if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
644
- const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
645
- selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
646
- }
663
+ const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
647
664
  const deepLinkKeysFromSelection = selectedDeepLink?.keys;
648
665
  let deepLinkKeysArray = [];
649
666
  if (Array.isArray(button?.deepLinkKeys)) {
@@ -671,12 +688,7 @@ const MediaUploaders = ({
671
688
  onChange={(e) => handleCarouselDeepLinkKeysChange(cardIndex, e.target.value)}
672
689
  placeholder={formatMessage(messages.deepLinkKeysPlaceholder, {
673
690
  key: (() => {
674
- // Try to find exact match first, then try match without query parameters
675
- let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
676
- if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
677
- const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
678
- selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
679
- }
691
+ const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
680
692
  const deepLinkKeysFromSelection = selectedDeepLink?.keys;
681
693
  let deepLinkKeysFromSelectionArray = [];
682
694
  if (Array.isArray(deepLinkKeysFromSelection)) {
@@ -807,21 +819,44 @@ const MediaUploaders = ({
807
819
  carouselActiveTabIndex,
808
820
  uploadMpushAsset,
809
821
  isFullMode,
810
- setUpdateMpushImageSrc,
811
- updateOnMpushImageReUpload,
812
822
  imageData,
813
823
  videoAssetList,
814
824
  setUpdateMpushVideoSrc,
815
825
  videoDataForVideo,
816
826
  formatMessage,
817
- clearImageDataByMediaType,
818
827
  mobilePushActions,
819
828
  carouselLinkErrors,
820
829
  updateCarouselLinkError,
821
- carouselActiveTabIndex,
822
830
  setCarouselActiveTabIndex,
831
+ deepLink,
823
832
  ]);
824
833
 
834
+ // Manually handle upload completion for carousel cards (since automatic restoration is disabled)
835
+ useEffect(() => {
836
+ if (mediaType === CAROUSEL && uploadingCardIndex !== null && currentUploadId && imageData) {
837
+ const platformIndex = activeTab === ANDROID ? 0 : 1;
838
+ const uploadedData = imageData[`uploadedAssetData${platformIndex}`];
839
+
840
+ if (uploadedData && uploadedData.metaInfo && uploadedData.metaInfo.secure_file_path) {
841
+ // Check if this is new upload data (different from what we processed last time)
842
+ const currentDataKey = `${uploadedData.metaInfo.secure_file_path}_${uploadedData.metaInfo.file_name || ''}`;
843
+ const previousDataKey = previousUploadDataRef.current;
844
+
845
+ if (currentDataKey !== previousDataKey) {
846
+ // Update the specific card that was uploading
847
+ updateCarouselCard(uploadingCardIndex, { imageUrl: uploadedData.metaInfo.secure_file_path });
848
+
849
+ // Store this upload data as "processed" to avoid reprocessing
850
+ previousUploadDataRef.current = currentDataKey;
851
+
852
+ // Clear the uploading state
853
+ setUploadingCardIndex(null);
854
+ setCurrentUploadId(null);
855
+ }
856
+ }
857
+ }
858
+ }, [mediaType, imageData, uploadingCardIndex, currentUploadId, activeTab, updateCarouselCard]);
859
+
825
860
  if (mediaType === IMAGE) return renderImageComponent();
826
861
  if (mediaType === VIDEO) return renderVideoComponent();
827
862
  if (mediaType === GIF) return renderGifComponent();
@@ -63,7 +63,7 @@ const PlatformContentFields = ({
63
63
  let selectedDeepLink = deepLink?.find((link) => link?.value === deepLinkValue);
64
64
 
65
65
  // If no exact match, try to find match without query parameters
66
- if (!selectedDeepLink && deepLinkValue && deepLinkValue.includes('?')) {
66
+ if (!selectedDeepLink && deepLinkValue?.includes('?')) {
67
67
  const baseDeepLinkValue = deepLinkValue.split('?')[0];
68
68
  selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
69
69
  }