@capillarytech/creatives-library 8.0.125-alpha.6 → 8.0.126

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 (105) hide show
  1. package/config/app.js +6 -0
  2. package/containers/App/constants.js +0 -1
  3. package/containers/Email/index.js +5 -5
  4. package/containers/WeChat/RichmediaTemplates/Create/index.js +1 -1
  5. package/initialReducer.js +2 -0
  6. package/package.json +1 -1
  7. package/services/api.js +94 -1
  8. package/services/tests/api.test.js +191 -0
  9. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +3 -8
  10. package/tests/integration/TemplateCreation/api-response.js +0 -5
  11. package/tests/integration/TemplateCreation/msw-handler.js +63 -42
  12. package/utils/common.js +0 -7
  13. package/utils/commonUtils.js +6 -2
  14. package/v2Components/CapImageUpload/index.js +45 -51
  15. package/v2Components/CapInAppCTA/index.js +0 -1
  16. package/v2Components/CapTagList/index.js +120 -177
  17. package/v2Components/CapVideoUpload/constants.js +0 -3
  18. package/v2Components/CapVideoUpload/index.js +110 -167
  19. package/v2Components/CapVideoUpload/messages.js +0 -16
  20. package/v2Components/Carousel/index.js +13 -15
  21. package/v2Components/CustomerSearchSection/_customerSearch.scss +309 -0
  22. package/v2Components/CustomerSearchSection/constants.js +5 -0
  23. package/v2Components/CustomerSearchSection/index.js +362 -0
  24. package/v2Components/CustomerSearchSection/messages.js +20 -0
  25. package/v2Components/CustomerSearchSection/tests/utils.test.js +334 -0
  26. package/v2Components/CustomerSearchSection/utils.js +49 -0
  27. package/v2Components/ErrorInfoNote/style.scss +0 -1
  28. package/v2Components/MobilePushPreviewV2/index.js +5 -37
  29. package/v2Components/TemplatePreview/_templatePreview.scss +72 -114
  30. package/v2Components/TemplatePreview/index.js +50 -178
  31. package/v2Components/TemplatePreview/messages.js +0 -4
  32. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +543 -0
  33. package/v2Components/TestAndPreviewSlidebox/actions.js +67 -0
  34. package/v2Components/TestAndPreviewSlidebox/constants.js +67 -0
  35. package/v2Components/TestAndPreviewSlidebox/index.js +771 -0
  36. package/v2Components/TestAndPreviewSlidebox/messages.js +147 -0
  37. package/v2Components/TestAndPreviewSlidebox/reducer.js +233 -0
  38. package/v2Components/TestAndPreviewSlidebox/sagas.js +258 -0
  39. package/v2Components/TestAndPreviewSlidebox/selectors.js +142 -0
  40. package/v2Components/TestAndPreviewSlidebox/tests/actions.test.js +80 -0
  41. package/v2Components/TestAndPreviewSlidebox/tests/reducer.test.js +367 -0
  42. package/v2Components/TestAndPreviewSlidebox/tests/saga.rtl.test.js +192 -0
  43. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +652 -0
  44. package/v2Components/TestAndPreviewSlidebox/tests/selector.test.js +182 -0
  45. package/v2Containers/CreativesContainer/SlideBoxContent.js +21 -9
  46. package/v2Containers/CreativesContainer/SlideBoxFooter.js +23 -2
  47. package/v2Containers/CreativesContainer/index.js +160 -195
  48. package/v2Containers/CreativesContainer/messages.js +4 -0
  49. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +21 -0
  50. package/v2Containers/Email/index.js +18 -6
  51. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +10 -0
  52. package/v2Containers/EmailWrapper/index.js +6 -0
  53. package/v2Containers/InApp/constants.js +0 -1
  54. package/v2Containers/InApp/index.js +13 -13
  55. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  56. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  57. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  58. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  59. package/v2Containers/MobilePush/Create/index.js +0 -1
  60. package/v2Containers/MobilePush/commonMethods.js +14 -7
  61. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +23 -5
  62. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  63. package/v2Containers/TagList/index.js +10 -56
  64. package/v2Containers/Templates/_templates.scss +1 -101
  65. package/v2Containers/Templates/index.js +35 -147
  66. package/v2Containers/Templates/messages.js +0 -8
  67. package/v2Containers/Templates/sagas.js +0 -2
  68. package/v2Containers/WeChat/RichmediaTemplates/Create/index.js +1 -1
  69. package/v2Containers/Whatsapp/constants.js +0 -1
  70. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
  71. package/utils/createPayload.js +0 -270
  72. package/utils/tests/createPayload.test.js +0 -761
  73. package/v2Components/CapMpushCTA/constants.js +0 -25
  74. package/v2Components/CapMpushCTA/index.js +0 -332
  75. package/v2Components/CapMpushCTA/index.scss +0 -95
  76. package/v2Components/CapMpushCTA/messages.js +0 -89
  77. package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +0 -29
  78. package/v2Components/TemplatePreview/assets/images/android.svg +0 -9
  79. package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +0 -26
  80. package/v2Components/TemplatePreview/assets/images/ios.svg +0 -9
  81. package/v2Containers/Email/tests/index.test.js +0 -35
  82. package/v2Containers/MobilePushNew/actions.js +0 -116
  83. package/v2Containers/MobilePushNew/components/CtaButtons.js +0 -170
  84. package/v2Containers/MobilePushNew/components/MediaUploaders.js +0 -686
  85. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +0 -279
  86. package/v2Containers/MobilePushNew/components/index.js +0 -5
  87. package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +0 -779
  88. package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +0 -2114
  89. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +0 -343
  90. package/v2Containers/MobilePushNew/constants.js +0 -115
  91. package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +0 -1299
  92. package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +0 -1223
  93. package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +0 -246
  94. package/v2Containers/MobilePushNew/hooks/useUpload.js +0 -709
  95. package/v2Containers/MobilePushNew/index.js +0 -2170
  96. package/v2Containers/MobilePushNew/index.scss +0 -308
  97. package/v2Containers/MobilePushNew/messages.js +0 -226
  98. package/v2Containers/MobilePushNew/reducer.js +0 -160
  99. package/v2Containers/MobilePushNew/sagas.js +0 -198
  100. package/v2Containers/MobilePushNew/selectors.js +0 -55
  101. package/v2Containers/MobilePushNew/tests/reducer.test.js +0 -741
  102. package/v2Containers/MobilePushNew/tests/sagas.test.js +0 -863
  103. package/v2Containers/MobilePushNew/tests/selectors.test.js +0 -425
  104. package/v2Containers/MobilePushNew/tests/utils.test.js +0 -322
  105. package/v2Containers/MobilePushNew/utils.js +0 -33
@@ -1,709 +0,0 @@
1
- import { useState, useCallback, useEffect } from 'react';
2
- import { getCdnUrl } from '../../../utils/cdnTransformation';
3
- import {
4
- MOBILE_PUSH_CHANNEL,
5
- MPUSH_IMG_SIZE,
6
- MPUSH_VIDEO_SIZE,
7
- ALLOWED_IMAGE_EXTENSIONS_REGEX,
8
- ALLOWED_EXTENSIONS_VIDEO_REGEX,
9
- ALLOWED_GIF_REGEX,
10
- ANDROID,
11
- MPUSH_GIF_SIZE,
12
- IMAGE,
13
- VIDEO,
14
- GIF,
15
- CAROUSEL,
16
- } from '../constants';
17
-
18
- // eslint-disable-next-line no-unused-vars
19
- const useUpload = (mobilePushActions, editData = {}, _uploadedAssetData0 = {}, _uploadedAssetData1 = {}, _uploadAssetSuccess = false, sameContent = false, setAndroidContent, setIosContent, activeTab, _androidContent, _iosContent) => {
20
- // Asset list state - make platform-specific to prevent cross-platform bleeding
21
- const [androidAssetList, updateAndroidAssetList] = useState([]);
22
- const [iosAssetList, updateIosAssetList] = useState([]);
23
- const [mpushVideoSrcAndPreview, setMpushVideoSrcAndPreview] = useState({
24
- mpushVideoSrc: "",
25
- mpushVideoPreviewImg: "",
26
- duration: 0,
27
- });
28
-
29
- // Image state for non-carousel media types (IMAGE, VIDEO, GIF)
30
- const [imageSrc, setImageSrc] = useState({
31
- androidImageSrc: "",
32
- iosImageSrc: "",
33
- });
34
-
35
- // Video state for platform-specific video/GIF uploads
36
- const [videoState, setVideoState] = useState({
37
- androidVideoSrc: "",
38
- iosVideoSrc: "",
39
- androidVideoPreview: "",
40
- iosVideoPreview: "",
41
- androidVideoDuration: 0,
42
- iosVideoDuration: 0,
43
- });
44
-
45
- const [uploadErrors, setUploadErrors] = useState({});
46
-
47
- // Add assetList state for test assertions
48
- const [assetList, setAssetList] = useState([]);
49
-
50
- // Patch updateAndroidAssetList and updateIosAssetList to also update assetList for test visibility
51
- const updateAndroidAssetListPatched = (data) => {
52
- setAssetList(data);
53
- updateAndroidAssetList(data);
54
- };
55
- const updateIosAssetListPatched = (data) => {
56
- setAssetList(data);
57
- updateIosAssetList(data);
58
- };
59
-
60
- // File validation functions
61
- const validateImageFile = useCallback((file) => {
62
- const errors = [];
63
-
64
- // File size validation
65
- if (file.size > MPUSH_IMG_SIZE) {
66
- errors.push(`File size should be less than ${MPUSH_IMG_SIZE / 1000000}MB`);
67
- }
68
-
69
- // File type validation
70
- if (!ALLOWED_IMAGE_EXTENSIONS_REGEX.test(file.name)) {
71
- errors.push('Only JPEG and PNG files are allowed');
72
- }
73
-
74
- return errors;
75
- }, []);
76
-
77
- const validateVideoFile = useCallback((file) => {
78
- const errors = [];
79
-
80
- // File size validation
81
- if (file.size > MPUSH_VIDEO_SIZE) {
82
- errors.push(`File size should be less than ${MPUSH_VIDEO_SIZE / 1000000}MB`);
83
- }
84
-
85
- // File type validation for video
86
- if (!ALLOWED_EXTENSIONS_VIDEO_REGEX.test(file.name)) {
87
- errors.push('Only 3GP, MP4, MOV, M4V files are allowed');
88
- }
89
-
90
- return errors;
91
- }, []);
92
-
93
- const validateGifFile = useCallback((file) => {
94
- const errors = [];
95
-
96
- // File size validation
97
- if (file.size > MPUSH_GIF_SIZE) {
98
- errors.push(`File size should be less than ${MPUSH_GIF_SIZE / 1000000}MB`);
99
- }
100
-
101
- // File type validation for GIF
102
- if (!ALLOWED_GIF_REGEX.test(file.name)) {
103
- errors.push('Only GIF files are allowed');
104
- }
105
-
106
- return errors;
107
- }, []);
108
-
109
- // Upload asset function with validation
110
- const uploadMpushAsset = useCallback((file, type, fileParams) => {
111
- let validationErrors = [];
112
-
113
- // Validate based on file type
114
- if (type === IMAGE.toLowerCase()) {
115
- validationErrors = validateImageFile(file);
116
- } else if (type === VIDEO.toLowerCase()) {
117
- validationErrors = validateVideoFile(file);
118
- } else if (type === GIF.toLowerCase()) {
119
- validationErrors = validateGifFile(file);
120
- }
121
-
122
- // If validation fails, set errors and don't upload
123
- if (validationErrors.length > 0) {
124
- setUploadErrors({
125
- [activeTab === ANDROID ? 0 : 1]: validationErrors,
126
- });
127
- return;
128
- }
129
-
130
- // Clear previous errors and proceed with upload
131
- setUploadErrors({});
132
-
133
- // Use "video" as assetType for both video and gif uploads
134
- // since backend treats them the same way
135
- const assetType = (type === GIF.toLowerCase()) ? VIDEO.toLowerCase() : type;
136
-
137
- const mobilePushParams = {
138
- source: MOBILE_PUSH_CHANNEL.toLowerCase(),
139
- channel: MOBILE_PUSH_CHANNEL,
140
- };
141
- mobilePushActions.uploadAsset(file, assetType, fileParams, activeTab === ANDROID ? 0 : 1, mobilePushParams);
142
- }, [mobilePushActions, validateImageFile, validateVideoFile, validateGifFile, activeTab]);
143
-
144
- // Clear media data when switching media types
145
- const clearImageDataByMediaType = useCallback((mediaType) => {
146
- if (mediaType === IMAGE) {
147
- if (sameContent) {
148
- // When sync is enabled, clear both platforms
149
- setImageSrc({
150
- androidImageSrc: "",
151
- iosImageSrc: "",
152
- });
153
- } else {
154
- // When sync is disabled, only clear the current platform
155
- const platform = activeTab === ANDROID ? 'androidImageSrc' : 'iosImageSrc';
156
- setImageSrc((prevState) => ({
157
- ...prevState,
158
- [platform]: "",
159
- }));
160
- }
161
- } else if (mediaType === VIDEO || mediaType === GIF) {
162
- if (sameContent) {
163
- // When sync is enabled, clear both platforms
164
- setVideoState({
165
- androidVideoSrc: "",
166
- iosVideoSrc: "",
167
- androidVideoPreview: "",
168
- iosVideoPreview: "",
169
- androidVideoDuration: 0,
170
- iosVideoDuration: 0,
171
- });
172
-
173
- // Clear video data from both platform contents
174
- setAndroidContent((prevContent) => ({
175
- ...prevContent,
176
- videoSrc: "",
177
- videoPreview: "",
178
- videoDuration: 0,
179
- }));
180
- setIosContent((prevContent) => ({
181
- ...prevContent,
182
- videoSrc: "",
183
- videoPreview: "",
184
- videoDuration: 0,
185
- }));
186
-
187
- // Clear Redux uploadedAssetData for both platforms
188
- mobilePushActions.clearAsset(0);
189
- mobilePushActions.clearAsset(1);
190
- } else {
191
- // When sync is disabled, only clear the current platform
192
- const platformIndex = activeTab === ANDROID ? 0 : 1;
193
- const isAndroid = activeTab === ANDROID;
194
-
195
- setVideoState((prevState) => ({
196
- ...prevState,
197
- [isAndroid ? 'androidVideoSrc' : 'iosVideoSrc']: "",
198
- [isAndroid ? 'androidVideoPreview' : 'iosVideoPreview']: "",
199
- [isAndroid ? 'androidVideoDuration' : 'iosVideoDuration']: 0,
200
- }));
201
-
202
- // Clear video data from current platform content only
203
- if (isAndroid) {
204
- setAndroidContent((prevContent) => ({
205
- ...prevContent,
206
- videoSrc: "",
207
- videoPreview: "",
208
- videoDuration: 0,
209
- }));
210
- } else {
211
- setIosContent((prevContent) => ({
212
- ...prevContent,
213
- videoSrc: "",
214
- videoPreview: "",
215
- videoDuration: 0,
216
- }));
217
- }
218
-
219
- // Clear Redux uploadedAssetData for current platform only
220
- mobilePushActions.clearAsset(platformIndex);
221
- }
222
- }
223
- }, [setVideoState, mobilePushActions, sameContent, activeTab, setAndroidContent, setIosContent]);
224
-
225
- useEffect(() => {
226
- if (sameContent) {
227
- // When sync is enabled, update both platforms with the same image
228
- const sharedImageSrc = imageSrc.androidImageSrc || imageSrc.iosImageSrc;
229
- setAndroidContent((prevAndroidContent) => ({
230
- ...prevAndroidContent,
231
- imageSrc: sharedImageSrc,
232
- }));
233
- setIosContent((prevIosContent) => ({
234
- ...prevIosContent,
235
- imageSrc: sharedImageSrc,
236
- }));
237
- } else {
238
- // When sync is disabled, update only the respective platform
239
- setAndroidContent((prevAndroidContent) => ({
240
- ...prevAndroidContent,
241
- imageSrc: imageSrc.androidImageSrc,
242
- }));
243
- setIosContent((prevIosContent) => ({
244
- ...prevIosContent,
245
- imageSrc: imageSrc.iosImageSrc,
246
- }));
247
- }
248
- }, [imageSrc.androidImageSrc, imageSrc.iosImageSrc, sameContent]);
249
-
250
- useEffect(() => {
251
- if (sameContent) {
252
- // When sync is enabled, update both platforms with the same video
253
- const sharedVideoSrc = videoState.androidVideoSrc || videoState.iosVideoSrc;
254
- const sharedVideoPreview = videoState.androidVideoPreview || videoState.iosVideoPreview;
255
- const sharedVideoDuration = videoState.androidVideoDuration || videoState.iosVideoDuration;
256
-
257
- setAndroidContent((prevAndroidContent) => ({
258
- ...prevAndroidContent,
259
- videoSrc: sharedVideoSrc,
260
- videoPreview: sharedVideoPreview,
261
- videoDuration: sharedVideoDuration,
262
- }));
263
- setIosContent((prevIosContent) => ({
264
- ...prevIosContent,
265
- videoSrc: sharedVideoSrc,
266
- videoPreview: sharedVideoPreview,
267
- videoDuration: sharedVideoDuration,
268
- }));
269
- } else {
270
- // When sync is disabled, update only the respective platform
271
- setAndroidContent((prevAndroidContent) => ({
272
- ...prevAndroidContent,
273
- videoSrc: videoState.androidVideoSrc,
274
- videoPreview: videoState.androidVideoPreview,
275
- videoDuration: videoState.androidVideoDuration,
276
- }));
277
- setIosContent((prevIosContent) => ({
278
- ...prevIosContent,
279
- videoSrc: videoState.iosVideoSrc,
280
- videoPreview: videoState.iosVideoPreview,
281
- videoDuration: videoState.iosVideoDuration,
282
- }));
283
- }
284
- }, [videoState.androidVideoSrc, videoState.iosVideoSrc, videoState.androidVideoPreview, videoState.iosVideoPreview, videoState.androidVideoDuration, videoState.iosVideoDuration, sameContent]);
285
-
286
- // Sync imageSrc state for both platforms when sameContent is toggled ON
287
- useEffect(() => {
288
- if (sameContent) {
289
- // Determine which image to use (prefer activeTab, fallback to either)
290
- let currentImageSrc = '';
291
- if (activeTab === ANDROID) {
292
- currentImageSrc = imageSrc.androidImageSrc || imageSrc.iosImageSrc;
293
- } else {
294
- currentImageSrc = imageSrc.iosImageSrc || imageSrc.androidImageSrc;
295
- }
296
- if (currentImageSrc && (imageSrc.androidImageSrc !== currentImageSrc || imageSrc.iosImageSrc !== currentImageSrc)) {
297
- setImageSrc({
298
- androidImageSrc: currentImageSrc,
299
- iosImageSrc: currentImageSrc,
300
- });
301
- }
302
- }
303
- // Only run when sameContent or activeTab changes
304
- // eslint-disable-next-line react-hooks/exhaustive-deps
305
- }, [sameContent, activeTab]);
306
-
307
- // Sync videoState for both platforms when sameContent is toggled ON
308
- useEffect(() => {
309
- if (sameContent) {
310
- // Determine which video to use (prefer activeTab, fallback to either)
311
- let currentVideoSrc = '';
312
- let currentVideoPreview = '';
313
- let currentVideoDuration = 0;
314
- if (activeTab === ANDROID) {
315
- currentVideoSrc = videoState.androidVideoSrc || videoState.iosVideoSrc;
316
- currentVideoPreview = videoState.androidVideoPreview || videoState.iosVideoPreview;
317
- currentVideoDuration = videoState.androidVideoDuration || videoState.iosVideoDuration;
318
- } else {
319
- currentVideoSrc = videoState.iosVideoSrc || videoState.androidVideoSrc;
320
- currentVideoPreview = videoState.iosVideoPreview || videoState.androidVideoPreview;
321
- currentVideoDuration = videoState.iosVideoDuration || videoState.androidVideoDuration;
322
- }
323
- if (
324
- currentVideoSrc && (
325
- videoState.androidVideoSrc !== currentVideoSrc
326
- || videoState.iosVideoSrc !== currentVideoSrc
327
- || videoState.androidVideoPreview !== currentVideoPreview
328
- || videoState.iosVideoPreview !== currentVideoPreview
329
- || videoState.androidVideoDuration !== currentVideoDuration
330
- || videoState.iosVideoDuration !== currentVideoDuration
331
- )
332
- ) {
333
- setVideoState({
334
- androidVideoSrc: currentVideoSrc,
335
- iosVideoSrc: currentVideoSrc,
336
- androidVideoPreview: currentVideoPreview,
337
- iosVideoPreview: currentVideoPreview,
338
- androidVideoDuration: currentVideoDuration,
339
- iosVideoDuration: currentVideoDuration,
340
- });
341
- }
342
- }
343
- // Only run when sameContent or activeTab changes
344
- // eslint-disable-next-line react-hooks/exhaustive-deps
345
- }, [sameContent, activeTab]);
346
-
347
- // Image upload handlers
348
- const updateOnMpushImageReUpload = useCallback(() => {
349
- if (sameContent) {
350
- // When sync is enabled, set image for both platforms
351
- setImageSrc({
352
- androidImageSrc: "",
353
- iosImageSrc: "",
354
- });
355
- } else {
356
- const platform = activeTab === ANDROID ? 'androidImageSrc' : 'iosImageSrc';
357
- setImageSrc((prevState) => ({
358
- ...prevState,
359
- [platform]: "",
360
- }));
361
- }
362
- }, [sameContent, activeTab]);
363
-
364
- const setUpdateMpushImageSrc = useCallback((filePath, index, mediaType = IMAGE) => {
365
- // Only handle non-carousel media types here
366
- if (mediaType === CAROUSEL) {
367
- return;
368
- }
369
-
370
- if (sameContent) {
371
- // When sync is enabled, set image for both platforms
372
- setImageSrc({
373
- androidImageSrc: filePath,
374
- iosImageSrc: filePath,
375
- });
376
- } else {
377
- // When sync is disabled, set only for the specific platform using the passed index
378
- const platform = index === 0 ? 'androidImageSrc' : 'iosImageSrc';
379
- setImageSrc((prevState) => ({
380
- ...prevState,
381
- [platform]: filePath,
382
- }));
383
- }
384
-
385
- mobilePushActions.clearAsset(index);
386
- }, [mobilePushActions, sameContent, setImageSrc]);
387
-
388
- // Video re-upload handler - clear video data based on platform and sync settings
389
- const updateOnMpushVideoReUpload = useCallback(() => {
390
- // Clear shared video preview state (kept for backward compatibility)
391
- setMpushVideoSrcAndPreview({
392
- mpushVideoSrc: "",
393
- mpushVideoPreviewImg: "",
394
- duration: 0,
395
- });
396
-
397
- // Clear asset list to remove uploaded video data
398
- updateAndroidAssetListPatched([]);
399
- updateIosAssetListPatched([]);
400
-
401
- // Clear platform-specific video data
402
- if (sameContent) {
403
- // When sync is enabled, clear both platforms
404
- setVideoState({
405
- androidVideoSrc: "",
406
- iosVideoSrc: "",
407
- androidVideoPreview: "",
408
- iosVideoPreview: "",
409
- androidVideoDuration: 0,
410
- iosVideoDuration: 0,
411
- });
412
-
413
- // Clear Redux uploadedAssetData for both platforms
414
- mobilePushActions.clearAsset(0);
415
- mobilePushActions.clearAsset(1);
416
- } else {
417
- // When sync is disabled, only clear the current platform
418
- const platformIndex = activeTab === ANDROID ? 0 : 1;
419
- const isAndroid = activeTab === ANDROID;
420
-
421
- setVideoState((prevState) => ({
422
- ...prevState,
423
- [isAndroid ? 'androidVideoSrc' : 'iosVideoSrc']: "",
424
- [isAndroid ? 'androidVideoPreview' : 'iosVideoPreview']: "",
425
- [isAndroid ? 'androidVideoDuration' : 'iosVideoDuration']: 0,
426
- }));
427
-
428
- // Clear Redux uploadedAssetData for current platform only
429
- mobilePushActions.clearAsset(platformIndex);
430
- }
431
- }, [setVideoState, mobilePushActions, sameContent, activeTab]);
432
-
433
- // Video upload handlers - platform-specific video/GIF uploads
434
- const setUpdateMpushVideoSrc = useCallback((index, data, isInitialization = false) => {
435
- const {
436
- videoSrc = "", previewUrl = "", videoDuration = 0, videoName = "", fileHandle = "",
437
- } = data;
438
-
439
- // Update the shared video preview state (kept for backward compatibility)
440
- setMpushVideoSrcAndPreview({
441
- mpushVideoSrc: videoSrc,
442
- mpushVideoPreviewImg: previewUrl,
443
- duration: videoDuration,
444
- });
445
-
446
- // Update platform-specific video state
447
- if (sameContent) {
448
- // When sync is enabled, set video for both platforms (for GIF or VIDEO)
449
- setVideoState({
450
- androidVideoSrc: videoSrc,
451
- iosVideoSrc: videoSrc,
452
- androidVideoPreview: previewUrl,
453
- iosVideoPreview: previewUrl,
454
- androidVideoDuration: videoDuration,
455
- iosVideoDuration: videoDuration,
456
- });
457
- } else {
458
- // When sync is disabled, set only for the specific platform using the passed index
459
- const isAndroid = index === 0;
460
- setVideoState((prevState) => ({
461
- ...prevState,
462
- [isAndroid ? 'androidVideoSrc' : 'iosVideoSrc']: videoSrc,
463
- [isAndroid ? 'androidVideoPreview' : 'iosVideoPreview']: previewUrl,
464
- [isAndroid ? 'androidVideoDuration' : 'iosVideoDuration']: videoDuration,
465
- }));
466
- }
467
-
468
- // Update asset list with complete data
469
- const assetData = {
470
- videoSrc,
471
- previewUrl,
472
- videoDuration,
473
- videoName,
474
- fileHandle,
475
- ...data, // Include any additional data passed
476
- };
477
- if (sameContent) {
478
- updateAndroidAssetListPatched(assetData);
479
- updateIosAssetListPatched(assetData);
480
- } else if (index === 0) {
481
- updateAndroidAssetListPatched(assetData);
482
- } else {
483
- updateIosAssetListPatched(assetData);
484
- }
485
-
486
- // Only clear Redux asset data during actual uploads, not during initialization
487
- if (!isInitialization) {
488
- mobilePushActions.clearAsset(index);
489
- }
490
- }, [mobilePushActions, sameContent]);
491
-
492
- // Get CDN URL for images/videos
493
- const getCdnImageUrl = useCallback((imageUrl) => {
494
- if (!imageUrl) return "";
495
- return getCdnUrl({
496
- url: imageUrl,
497
- channelName: MOBILE_PUSH_CHANNEL,
498
- });
499
- }, []);
500
-
501
- const getCdnVideoUrl = useCallback((videoUrl) => {
502
- if (!videoUrl) return "";
503
- return getCdnUrl({
504
- url: videoUrl,
505
- channelName: MOBILE_PUSH_CHANNEL,
506
- });
507
- }, []);
508
-
509
- // Generate payload for API calls
510
- const getMediaPayload = useCallback((mediaType, tabParam) => {
511
- const currentImageSrc = tabParam === ANDROID ? imageSrc.androidImageSrc : imageSrc.iosImageSrc;
512
- const currentVideoSrc = tabParam === ANDROID ? videoState.androidVideoSrc : videoState.iosVideoSrc;
513
- const currentVideoPreview = tabParam === ANDROID ? videoState.androidVideoPreview : videoState.iosVideoPreview;
514
- const currentVideoDuration = tabParam === ANDROID ? videoState.androidVideoDuration : videoState.iosVideoDuration;
515
-
516
- switch (mediaType) {
517
- case IMAGE:
518
- return currentImageSrc ? {
519
- imageUrl: getCdnImageUrl(currentImageSrc),
520
- } : {};
521
-
522
- case VIDEO:
523
- return currentVideoSrc ? {
524
- videoUrl: getCdnVideoUrl(currentVideoSrc),
525
- videoPreviewImg: currentVideoPreview
526
- ? getCdnImageUrl(currentVideoPreview) : "",
527
- duration: currentVideoDuration,
528
- } : {};
529
-
530
- case GIF:
531
- return currentVideoSrc ? {
532
- gifUrl: getCdnVideoUrl(currentVideoSrc),
533
- gifPreviewImg: currentVideoPreview
534
- ? getCdnImageUrl(currentVideoPreview) : "",
535
- } : {};
536
-
537
- default:
538
- return {};
539
- }
540
- }, [imageSrc, videoState, getCdnImageUrl, getCdnVideoUrl]);
541
-
542
- // Generate preview data for template preview component
543
- const getPreviewData = useCallback((mediaType, tabParam) => {
544
- const currentImageSrc = tabParam === ANDROID ? imageSrc.androidImageSrc : imageSrc.iosImageSrc;
545
- const currentVideoSrc = tabParam === ANDROID ? videoState.androidVideoSrc : videoState.iosVideoSrc;
546
- const currentVideoPreview = tabParam === ANDROID ? videoState.androidVideoPreview : videoState.iosVideoPreview;
547
- const currentVideoDuration = tabParam === ANDROID ? videoState.androidVideoDuration : videoState.iosVideoDuration;
548
-
549
- switch (mediaType) {
550
- case IMAGE:
551
- return {
552
- imageSrc: currentImageSrc,
553
- };
554
-
555
- case VIDEO:
556
- return {
557
- videoSrc: currentVideoSrc,
558
- videoPreviewImg: currentVideoPreview,
559
- duration: currentVideoDuration,
560
- };
561
-
562
- case GIF:
563
- return {
564
- gifSrc: currentVideoSrc,
565
- gifPreviewImg: currentVideoPreview,
566
- };
567
-
568
- default:
569
- return {};
570
- }
571
- }, [imageSrc, videoState]);
572
-
573
- // Check if media is uploaded for validation
574
- const isMediaUploaded = useCallback((mediaType, tabParam) => {
575
- switch (mediaType) {
576
- case IMAGE: {
577
- const currentImageSrc = tabParam === ANDROID ? imageSrc.androidImageSrc : imageSrc.iosImageSrc;
578
- return !!currentImageSrc;
579
- }
580
-
581
- case VIDEO:
582
- case GIF: {
583
- const currentVideoSrc = tabParam === ANDROID ? videoState.androidVideoSrc : videoState.iosVideoSrc;
584
- return !!currentVideoSrc;
585
- }
586
-
587
- default:
588
- return true; // For TEXT or NONE media types
589
- }
590
- }, [imageSrc, videoState]);
591
-
592
- // Reset function to clear all upload states
593
- const resetUploadStates = useCallback(() => {
594
- setImageSrc({
595
- androidImageSrc: "",
596
- iosImageSrc: "",
597
- });
598
- setMpushVideoSrcAndPreview({
599
- mpushVideoSrc: "",
600
- mpushVideoPreviewImg: "",
601
- duration: 0,
602
- });
603
- setVideoState({
604
- androidVideoSrc: "",
605
- iosVideoSrc: "",
606
- androidVideoPreview: "",
607
- iosVideoPreview: "",
608
- androidVideoDuration: 0,
609
- iosVideoDuration: 0,
610
- });
611
- updateAndroidAssetListPatched([]);
612
- updateIosAssetListPatched([]);
613
- }, []);
614
-
615
- // Initialize from edit data
616
- useEffect(() => {
617
- if (editData?.templateDetails) {
618
- const { versions = {} } = editData.templateDetails;
619
- const editContent = versions?.base?.content || {};
620
-
621
- if (editContent.ANDROID) {
622
- const { expandableDetails = {} } = editContent.ANDROID;
623
- if (expandableDetails.image) {
624
- setImageSrc((prev) => ({
625
- ...prev,
626
- androidImageSrc: expandableDetails.image,
627
- }));
628
- }
629
- if (expandableDetails.video) {
630
- // Update shared state for backward compatibility
631
- setMpushVideoSrcAndPreview((prev) => ({
632
- ...prev,
633
- mpushVideoSrc: expandableDetails.video,
634
- mpushVideoPreviewImg: expandableDetails.videoPreview || "",
635
- }));
636
-
637
- // Update platform-specific video state
638
- setVideoState((prev) => ({
639
- ...prev,
640
- androidVideoSrc: expandableDetails.video,
641
- androidVideoPreview: expandableDetails.videoPreview || "",
642
- androidVideoDuration: expandableDetails.videoDuration || 0,
643
- }));
644
- }
645
- }
646
-
647
- if (editContent.IOS) {
648
- const { expandableDetails = {} } = editContent.IOS;
649
- if (expandableDetails.image) {
650
- setImageSrc((prev) => ({
651
- ...prev,
652
- iosImageSrc: expandableDetails.image,
653
- }));
654
- }
655
- if (expandableDetails.video) {
656
- // Update platform-specific video state for iOS
657
- setVideoState((prev) => ({
658
- ...prev,
659
- iosVideoSrc: expandableDetails.video,
660
- iosVideoPreview: expandableDetails.videoPreview || "",
661
- iosVideoDuration: expandableDetails.videoDuration || 0,
662
- }));
663
- }
664
- }
665
- }
666
- }, [editData]);
667
-
668
- return {
669
- // States
670
- androidAssetList,
671
- iosAssetList,
672
- mpushVideoSrcAndPreview,
673
- imageSrc,
674
- videoState,
675
- uploadErrors,
676
- assetList, // Expose for test assertions
677
-
678
- // Functions
679
- uploadMpushAsset,
680
- updateOnMpushImageReUpload,
681
- updateOnMpushVideoReUpload,
682
- setUpdateMpushImageSrc,
683
- setUpdateMpushVideoSrc,
684
- resetUploadStates,
685
- clearImageDataByMediaType,
686
-
687
- // Validation functions
688
- validateImageFile,
689
- validateVideoFile,
690
- validateGifFile,
691
-
692
- // Utility functions
693
- getMediaPayload,
694
- getPreviewData,
695
- isMediaUploaded,
696
- getCdnImageUrl,
697
- getCdnVideoUrl,
698
-
699
- // State setters (for direct manipulation if needed)
700
- updateAndroidAssetList,
701
- updateIosAssetList,
702
- setMpushVideoSrcAndPreview,
703
- setImageSrc,
704
- setVideoState,
705
- setUploadErrors,
706
- };
707
- };
708
-
709
- export default useUpload;