@capillarytech/creatives-library 8.0.242-alpha.0 → 8.0.242-alpha.2
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/sagas/__tests__/assetPolling.test.js +74 -3
- package/sagas/assetPolling.js +8 -1
- package/services/api.js +10 -5
- package/services/tests/api.test.js +18 -0
- package/translations/en.json +0 -1
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +14 -1
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/utils/transformerUtils.js +0 -42
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapImageUpload/constants.js +0 -2
- package/v2Components/CapImageUpload/index.js +14 -54
- package/v2Components/CapImageUpload/index.scss +1 -4
- package/v2Components/CapImageUpload/messages.js +0 -4
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/index.js +412 -72
- package/v2Components/ErrorInfoNote/messages.js +22 -0
- package/v2Components/ErrorInfoNote/style.scss +279 -2
- package/v2Components/HtmlEditor/HTMLEditor.js +217 -90
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1132 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
- package/v2Components/HtmlEditor/_htmlEditor.scss +15 -23
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +1 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +1 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +10 -11
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +87 -62
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +362 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +29 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +99 -101
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +34 -41
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +31 -25
- package/v2Containers/App/constants.js +0 -5
- package/v2Containers/BeeEditor/index.js +82 -80
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +193 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +0 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +148 -120
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
- package/v2Containers/CreativesContainer/constants.js +1 -2
- package/v2Containers/CreativesContainer/index.js +173 -193
- package/v2Containers/CreativesContainer/messages.js +4 -4
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +36 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +13 -0
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +41 -6
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1046 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +436 -67
- package/v2Containers/EmailWrapper/index.js +99 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +26 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +111 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +800 -357
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -25
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -18
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -46
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -8
- package/v2Containers/TagList/index.js +67 -1
- package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
- package/v2Containers/Templates/_templates.scss +56 -200
- package/v2Containers/Templates/actions.js +1 -2
- package/v2Containers/Templates/constants.js +0 -1
- package/v2Containers/Templates/index.js +124 -277
- package/v2Containers/Templates/messages.js +4 -24
- package/v2Containers/Templates/reducer.js +0 -2
- package/v2Containers/Templates/tests/index.test.js +0 -10
- package/v2Containers/TemplatesV2/index.js +2 -3
- package/v2Containers/TemplatesV2/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -132
- package/v2Components/CapImageUrlUpload/constants.js +0 -19
- package/v2Components/CapImageUrlUpload/index.js +0 -455
- package/v2Components/CapImageUrlUpload/index.scss +0 -35
- package/v2Components/CapImageUrlUpload/messages.js +0 -47
- package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -175
- package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
- package/v2Containers/WebPush/Create/components/ButtonList.js +0 -144
- package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
- package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
- package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
- package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -80
- package/v2Containers/WebPush/Create/index.js +0 -1755
- package/v2Containers/WebPush/Create/index.scss +0 -123
- package/v2Containers/WebPush/Create/messages.js +0 -199
- package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -241
- package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -290
- package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -81
- package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -240
- package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -144
- package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
- package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
- package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
- package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
- package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
- package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -44
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -110
- package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
- package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -72
- package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -55
- package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -70
- package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -512
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -77
- package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -527
- package/v2Containers/WebPush/Create/preview/constants.js +0 -162
- package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -104
- package/v2Containers/WebPush/Create/preview/preview.scss +0 -409
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -300
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -303
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -188
- package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -106
- package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
- package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -75
- package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -174
- package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1077
- package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -943
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -128
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -121
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -127
- package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -116
- package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
- package/v2Containers/WebPush/actions.js +0 -60
- package/v2Containers/WebPush/constants.js +0 -108
- package/v2Containers/WebPush/index.js +0 -2
- package/v2Containers/WebPush/reducer.js +0 -104
- package/v2Containers/WebPush/sagas.js +0 -119
- package/v2Containers/WebPush/selectors.js +0 -65
- package/v2Containers/WebPush/tests/reducer.test.js +0 -863
- package/v2Containers/WebPush/tests/sagas.test.js +0 -566
- package/v2Containers/WebPush/tests/selectors.test.js +0 -960
|
@@ -4,133 +4,30 @@
|
|
|
4
4
|
* Manages separate HTML content for Android and iOS devices with sync functionality
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
useState, useCallback, useRef, useEffect, useMemo,
|
|
9
|
+
} from 'react';
|
|
8
10
|
import { DEVICE_TYPES, PERFORMANCE } from '../constants';
|
|
9
11
|
|
|
10
12
|
// Constants for better maintainability
|
|
11
13
|
const CONTENT_VALIDATION = {
|
|
12
14
|
MIN_CONTENT_LENGTH: 0,
|
|
13
|
-
DEFAULT_CONTENT_TYPE: 'string'
|
|
15
|
+
DEFAULT_CONTENT_TYPE: 'string',
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
const AUTO_SAVE_CONFIG = {
|
|
17
19
|
DEFAULT_ENABLED: true,
|
|
18
20
|
DEFAULT_INTERVAL: PERFORMANCE.AUTO_SAVE_INTERVAL,
|
|
19
|
-
MIN_AUTO_SAVE_INTERVAL_MS: 1000 // Minimum 1 second between auto-saves
|
|
21
|
+
MIN_AUTO_SAVE_INTERVAL_MS: 1000, // Minimum 1 second between auto-saves
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* Default InApp content for different devices
|
|
26
|
+
* Empty strings - no default content for new templates
|
|
24
27
|
*/
|
|
25
28
|
const DEFAULT_INAPP_CONTENT = {
|
|
26
|
-
[DEVICE_TYPES.ANDROID]:
|
|
27
|
-
|
|
28
|
-
<head>
|
|
29
|
-
<meta charset="UTF-8">
|
|
30
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
31
|
-
<title>In-App Notification</title>
|
|
32
|
-
<style>
|
|
33
|
-
body {
|
|
34
|
-
margin: 0;
|
|
35
|
-
padding: 16px;
|
|
36
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Roboto', sans-serif;
|
|
37
|
-
background-color: #ffffff;
|
|
38
|
-
color: #212121;
|
|
39
|
-
}
|
|
40
|
-
.notification {
|
|
41
|
-
max-width: 100%;
|
|
42
|
-
background: white;
|
|
43
|
-
border-radius: 8px;
|
|
44
|
-
padding: 16px;
|
|
45
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
46
|
-
}
|
|
47
|
-
.title {
|
|
48
|
-
font-size: 16px;
|
|
49
|
-
font-weight: 500;
|
|
50
|
-
margin: 0 0 8px 0;
|
|
51
|
-
color: #212121;
|
|
52
|
-
}
|
|
53
|
-
.message {
|
|
54
|
-
font-size: 14px;
|
|
55
|
-
line-height: 1.4;
|
|
56
|
-
margin: 0 0 16px 0;
|
|
57
|
-
color: #424242;
|
|
58
|
-
}
|
|
59
|
-
.cta-button {
|
|
60
|
-
background-color: #42b040;
|
|
61
|
-
color: white;
|
|
62
|
-
border: none;
|
|
63
|
-
border-radius: 4px;
|
|
64
|
-
padding: 8px 16px;
|
|
65
|
-
font-size: 12px;
|
|
66
|
-
font-weight: 500;
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
width: 100%;
|
|
69
|
-
}
|
|
70
|
-
</style>
|
|
71
|
-
</head>
|
|
72
|
-
<body>
|
|
73
|
-
<div class="notification">
|
|
74
|
-
<h2 class="title">Sample template</h2>
|
|
75
|
-
<p class="message">This is a sample template for in-app notification content. This can be triggered on any behavioural event while the user is on the app</p>
|
|
76
|
-
<button class="cta-button">Add to cart</button>
|
|
77
|
-
</div>
|
|
78
|
-
</body>
|
|
79
|
-
</html>`,
|
|
80
|
-
[DEVICE_TYPES.IOS]: `<!DOCTYPE html>
|
|
81
|
-
<html lang="en">
|
|
82
|
-
<head>
|
|
83
|
-
<meta charset="UTF-8">
|
|
84
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
85
|
-
<title>In-App Notification</title>
|
|
86
|
-
<style>
|
|
87
|
-
body {
|
|
88
|
-
margin: 0;
|
|
89
|
-
padding: 16px;
|
|
90
|
-
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', sans-serif;
|
|
91
|
-
background-color: #ffffff;
|
|
92
|
-
color: #000000;
|
|
93
|
-
}
|
|
94
|
-
.notification {
|
|
95
|
-
max-width: 100%;
|
|
96
|
-
background: white;
|
|
97
|
-
border-radius: 12px;
|
|
98
|
-
padding: 16px;
|
|
99
|
-
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
|
|
100
|
-
}
|
|
101
|
-
.title {
|
|
102
|
-
font-size: 17px;
|
|
103
|
-
font-weight: 600;
|
|
104
|
-
margin: 0 0 8px 0;
|
|
105
|
-
color: #000000;
|
|
106
|
-
}
|
|
107
|
-
.message {
|
|
108
|
-
font-size: 15px;
|
|
109
|
-
line-height: 1.4;
|
|
110
|
-
margin: 0 0 16px 0;
|
|
111
|
-
color: #3c3c43;
|
|
112
|
-
}
|
|
113
|
-
.cta-button {
|
|
114
|
-
background-color: #007AFF;
|
|
115
|
-
color: white;
|
|
116
|
-
border: none;
|
|
117
|
-
border-radius: 8px;
|
|
118
|
-
padding: 12px 16px;
|
|
119
|
-
font-size: 16px;
|
|
120
|
-
font-weight: 600;
|
|
121
|
-
cursor: pointer;
|
|
122
|
-
width: 100%;
|
|
123
|
-
}
|
|
124
|
-
</style>
|
|
125
|
-
</head>
|
|
126
|
-
<body>
|
|
127
|
-
<div class="notification">
|
|
128
|
-
<h2 class="title">Sample template</h2>
|
|
129
|
-
<p class="message">This is a sample template for in-app notification content. This can be triggered on any behavioural event while the user is on the app</p>
|
|
130
|
-
<button class="cta-button">Add to cart</button>
|
|
131
|
-
</div>
|
|
132
|
-
</body>
|
|
133
|
-
</html>`
|
|
29
|
+
[DEVICE_TYPES.ANDROID]: '',
|
|
30
|
+
[DEVICE_TYPES.IOS]: '',
|
|
134
31
|
};
|
|
135
32
|
|
|
136
33
|
/**
|
|
@@ -150,7 +47,7 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
150
47
|
autoSave = AUTO_SAVE_CONFIG.DEFAULT_ENABLED,
|
|
151
48
|
autoSaveInterval = AUTO_SAVE_CONFIG.DEFAULT_INTERVAL,
|
|
152
49
|
onSave,
|
|
153
|
-
onChange
|
|
50
|
+
onChange,
|
|
154
51
|
} = options;
|
|
155
52
|
|
|
156
53
|
// Destructure device types for cleaner code
|
|
@@ -159,7 +56,7 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
159
56
|
// Device-specific content state with optional chaining
|
|
160
57
|
const [deviceContent, setDeviceContent] = useState(() => ({
|
|
161
58
|
[ANDROID]: initialContent?.[ANDROID] || DEFAULT_INAPP_CONTENT[ANDROID],
|
|
162
|
-
[IOS]: initialContent?.[IOS] || DEFAULT_INAPP_CONTENT[IOS]
|
|
59
|
+
[IOS]: initialContent?.[IOS] || DEFAULT_INAPP_CONTENT[IOS],
|
|
163
60
|
}));
|
|
164
61
|
|
|
165
62
|
// Current active device
|
|
@@ -189,15 +86,67 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
189
86
|
deviceContentRef.current = deviceContent;
|
|
190
87
|
}, [deviceContent]);
|
|
191
88
|
|
|
89
|
+
// Ref to track if we've loaded initial content to prevent overriding user edits
|
|
90
|
+
const initialContentLoadedRef = useRef(false);
|
|
91
|
+
const previousContentRef = useRef({ android: '', ios: '' });
|
|
92
|
+
|
|
93
|
+
// Update content when initialContent prop changes (for edit mode)
|
|
94
|
+
// This should only run when loading a template for editing, NOT during active editing
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const newAndroidContent = initialContent?.[ANDROID];
|
|
97
|
+
const newIosContent = initialContent?.[IOS];
|
|
98
|
+
|
|
99
|
+
// Check if this is meaningful initialContent (has actual content)
|
|
100
|
+
const hasMeaningfulContent = (newAndroidContent && newAndroidContent.trim() !== '')
|
|
101
|
+
|| (newIosContent && newIosContent.trim() !== '');
|
|
102
|
+
|
|
103
|
+
// Check if we're transitioning from empty to meaningful content (library mode scenario)
|
|
104
|
+
const wasEmpty = (!previousContentRef.current.android || previousContentRef.current.android.trim() === '')
|
|
105
|
+
&& (!previousContentRef.current.ios || previousContentRef.current.ios.trim() === '');
|
|
106
|
+
const isTransitioningToContent = wasEmpty && hasMeaningfulContent;
|
|
107
|
+
|
|
108
|
+
// Only update if:
|
|
109
|
+
// 1. We haven't loaded initial content yet (first load), OR
|
|
110
|
+
// 2. We're transitioning from empty to meaningful content (library mode data fetch)
|
|
111
|
+
// This prevents the effect from overriding user edits during active editing
|
|
112
|
+
// while still allowing content to load properly in library mode
|
|
113
|
+
if (!initialContentLoadedRef.current || isTransitioningToContent) {
|
|
114
|
+
if (hasMeaningfulContent) {
|
|
115
|
+
// Mark as loaded to prevent future updates from overriding user edits
|
|
116
|
+
initialContentLoadedRef.current = true;
|
|
117
|
+
|
|
118
|
+
setDeviceContent((prev) => {
|
|
119
|
+
let updated = false;
|
|
120
|
+
const updatedContent = { ...prev };
|
|
121
|
+
|
|
122
|
+
if (newAndroidContent !== undefined && newAndroidContent !== prev[ANDROID]) {
|
|
123
|
+
updatedContent[ANDROID] = newAndroidContent;
|
|
124
|
+
updated = true;
|
|
125
|
+
}
|
|
126
|
+
if (newIosContent !== undefined && newIosContent !== prev[IOS]) {
|
|
127
|
+
updatedContent[IOS] = newIosContent;
|
|
128
|
+
updated = true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return updated ? updatedContent : prev;
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Update previous content ref
|
|
135
|
+
previousContentRef.current = {
|
|
136
|
+
android: newAndroidContent || '',
|
|
137
|
+
ios: newIosContent || '',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}, [initialContent, ANDROID, IOS]);
|
|
142
|
+
|
|
192
143
|
// Get current active content
|
|
193
|
-
const currentContent = useMemo(() =>
|
|
194
|
-
return deviceContent[activeDevice] || '';
|
|
195
|
-
}, [deviceContent, activeDevice]);
|
|
144
|
+
const currentContent = useMemo(() => deviceContent?.[activeDevice] || '', [deviceContent, activeDevice]);
|
|
196
145
|
|
|
197
146
|
// Update content for current device
|
|
198
147
|
const updateContent = useCallback((newContent) => {
|
|
199
148
|
// Validate input
|
|
200
|
-
if (typeof newContent !== CONTENT_VALIDATION
|
|
149
|
+
if (typeof newContent !== CONTENT_VALIDATION?.DEFAULT_CONTENT_TYPE) {
|
|
201
150
|
console.warn('useInAppContent: newContent must be a string');
|
|
202
151
|
return;
|
|
203
152
|
}
|
|
@@ -209,14 +158,14 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
209
158
|
// When sync is enabled, update both devices with the same content
|
|
210
159
|
updatedDeviceContent = {
|
|
211
160
|
[ANDROID]: newContent,
|
|
212
|
-
[IOS]: newContent
|
|
161
|
+
[IOS]: newContent,
|
|
213
162
|
};
|
|
214
163
|
} else {
|
|
215
164
|
// When sync is disabled, update only the current device
|
|
216
|
-
setDeviceContent(prev => {
|
|
165
|
+
setDeviceContent((prev) => {
|
|
217
166
|
updatedDeviceContent = {
|
|
218
167
|
...prev,
|
|
219
|
-
[activeDevice]: newContent
|
|
168
|
+
[activeDevice]: newContent,
|
|
220
169
|
};
|
|
221
170
|
return updatedDeviceContent;
|
|
222
171
|
});
|
|
@@ -225,8 +174,9 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
225
174
|
setIsDirty(true);
|
|
226
175
|
changeTimestampRef.current = Date.now();
|
|
227
176
|
|
|
228
|
-
// Trigger onChange callback
|
|
229
|
-
|
|
177
|
+
// Trigger onChange callback - pass only changed device content
|
|
178
|
+
// This prevents parent from updating both device states when only one changed
|
|
179
|
+
onChange?.({ [activeDevice]: newContent }, activeDevice);
|
|
230
180
|
|
|
231
181
|
// Setup auto-save for independent mode
|
|
232
182
|
if (autoSave && autoSaveInterval > AUTO_SAVE_CONFIG.MIN_AUTO_SAVE_INTERVAL_MS && newContent.length > CONTENT_VALIDATION.MIN_CONTENT_LENGTH) {
|
|
@@ -257,7 +207,7 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
257
207
|
setIsDirty(true);
|
|
258
208
|
changeTimestampRef.current = Date.now();
|
|
259
209
|
|
|
260
|
-
// Trigger onChange callback
|
|
210
|
+
// Trigger onChange callback - in sync mode, pass full content
|
|
261
211
|
onChange?.(updatedDeviceContent, activeDevice);
|
|
262
212
|
|
|
263
213
|
// Setup auto-save
|
|
@@ -301,7 +251,7 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
301
251
|
const currentActiveContent = deviceContent[activeDevice];
|
|
302
252
|
const syncedContent = {
|
|
303
253
|
[ANDROID]: currentActiveContent,
|
|
304
|
-
[IOS]: currentActiveContent
|
|
254
|
+
[IOS]: currentActiveContent,
|
|
305
255
|
};
|
|
306
256
|
|
|
307
257
|
setDeviceContent(syncedContent);
|
|
@@ -325,22 +275,16 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
325
275
|
}, [deviceContent, onSave]);
|
|
326
276
|
|
|
327
277
|
// Check if content exists for current device
|
|
328
|
-
const hasContent = useMemo(() =>
|
|
329
|
-
|
|
330
|
-
currentContent.trim().length > CONTENT_VALIDATION.MIN_CONTENT_LENGTH;
|
|
331
|
-
}, [currentContent]);
|
|
278
|
+
const hasContent = useMemo(() => typeof currentContent === CONTENT_VALIDATION.DEFAULT_CONTENT_TYPE
|
|
279
|
+
&& currentContent?.trim()?.length > CONTENT_VALIDATION.MIN_CONTENT_LENGTH, [currentContent]);
|
|
332
280
|
|
|
333
281
|
// Get content size for current device
|
|
334
|
-
const getContentSize = useCallback(() =>
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
: CONTENT_VALIDATION.MIN_CONTENT_LENGTH;
|
|
338
|
-
}, [currentContent]);
|
|
282
|
+
const getContentSize = useCallback(() => typeof currentContent === CONTENT_VALIDATION.DEFAULT_CONTENT_TYPE
|
|
283
|
+
? currentContent?.length
|
|
284
|
+
: CONTENT_VALIDATION?.MIN_CONTENT_LENGTH, [currentContent]);
|
|
339
285
|
|
|
340
286
|
// Get content for specific device
|
|
341
|
-
const getDeviceContent = useCallback((device) =>
|
|
342
|
-
return deviceContent[device] || '';
|
|
343
|
-
}, [deviceContent]);
|
|
287
|
+
const getDeviceContent = useCallback((device) => deviceContent[device] || '', [deviceContent]);
|
|
344
288
|
|
|
345
289
|
// Set content for specific device
|
|
346
290
|
const setDeviceContent_ = useCallback((device, content) => {
|
|
@@ -360,25 +304,23 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
360
304
|
// Update both devices when sync is enabled
|
|
361
305
|
setDeviceContent({
|
|
362
306
|
[ANDROID]: content,
|
|
363
|
-
[IOS]: content
|
|
307
|
+
[IOS]: content,
|
|
364
308
|
});
|
|
365
309
|
} else {
|
|
366
310
|
// Update specific device
|
|
367
|
-
setDeviceContent(prev => ({
|
|
311
|
+
setDeviceContent((prev) => ({
|
|
368
312
|
...prev,
|
|
369
|
-
[device]: content
|
|
313
|
+
[device]: content,
|
|
370
314
|
}));
|
|
371
315
|
}
|
|
372
316
|
setIsDirty(true);
|
|
373
317
|
}, [keepContentSame, ANDROID, IOS]);
|
|
374
318
|
|
|
375
319
|
// Cleanup on unmount
|
|
376
|
-
useEffect(() => {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
};
|
|
320
|
+
useEffect(() => () => {
|
|
321
|
+
if (autoSaveTimerRef.current) {
|
|
322
|
+
clearTimeout(autoSaveTimerRef.current);
|
|
323
|
+
}
|
|
382
324
|
}, []);
|
|
383
325
|
|
|
384
326
|
return {
|
|
@@ -402,6 +344,6 @@ export const useInAppContent = (initialContent = {}, options = {}) => {
|
|
|
402
344
|
toggleContentSync,
|
|
403
345
|
|
|
404
346
|
// Save management
|
|
405
|
-
markAsSaved
|
|
347
|
+
markAsSaved,
|
|
406
348
|
};
|
|
407
349
|
};
|