@capillarytech/creatives-library 8.0.316 → 8.0.317-alpha.0

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 (172) hide show
  1. package/constants/unified.js +15 -0
  2. package/package.json +1 -1
  3. package/services/api.js +6 -0
  4. package/services/tests/api.test.js +7 -0
  5. package/utils/common.js +6 -1
  6. package/utils/templateVarUtils.js +172 -0
  7. package/utils/tests/tagValidations.test.js +34 -0
  8. package/utils/tests/templateVarUtils.test.js +160 -0
  9. package/v2Components/CapTagList/index.js +25 -22
  10. package/v2Components/CapTagList/style.scss +48 -0
  11. package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  12. package/v2Components/CapTagListWithInput/index.js +4 -0
  13. package/v2Components/CapWhatsappCTA/index.js +2 -0
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  21. package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
  22. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  24. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
  25. package/v2Components/CommonTestAndPreview/constants.js +38 -0
  26. package/v2Components/CommonTestAndPreview/index.js +693 -155
  27. package/v2Components/CommonTestAndPreview/messages.js +41 -3
  28. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  29. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  30. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  31. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
  32. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  33. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  34. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
  35. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  36. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
  37. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  38. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  39. package/v2Components/FormBuilder/index.js +14 -1
  40. package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
  41. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  42. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
  43. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
  44. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  45. package/v2Components/SmsFallback/constants.js +73 -0
  46. package/v2Components/SmsFallback/index.js +956 -0
  47. package/v2Components/SmsFallback/index.scss +265 -0
  48. package/v2Components/SmsFallback/messages.js +78 -0
  49. package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  50. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  51. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  52. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  53. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  54. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  55. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  56. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  57. package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
  58. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  59. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  60. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  61. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  62. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  63. package/v2Containers/BeeEditor/index.js +3 -0
  64. package/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  65. package/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  66. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  67. package/v2Containers/CommunicationFlow/constants.js +200 -0
  68. package/v2Containers/CommunicationFlow/index.js +102 -0
  69. package/v2Containers/CommunicationFlow/messages.js +346 -0
  70. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  71. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  72. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  73. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  74. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  75. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  76. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  77. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  78. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  79. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  80. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  81. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  82. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  83. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  84. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  85. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  86. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  87. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  88. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  89. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  90. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  91. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  92. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  93. package/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  94. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  95. package/v2Containers/CreativesContainer/SlideBoxContent.js +64 -5
  96. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  97. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  98. package/v2Containers/CreativesContainer/constants.js +12 -0
  99. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  100. package/v2Containers/CreativesContainer/index.js +289 -93
  101. package/v2Containers/CreativesContainer/index.scss +51 -1
  102. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  103. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
  104. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  105. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  106. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  107. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
  108. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  109. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  110. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  111. package/v2Containers/Email/index.js +1 -0
  112. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +7 -1
  113. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  114. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
  115. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  116. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -0
  117. package/v2Containers/EmailWrapper/index.js +4 -0
  118. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  119. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
  120. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  121. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  122. package/v2Containers/InAppWrapper/index.js +3 -0
  123. package/v2Containers/MobilePush/Create/index.js +2 -0
  124. package/v2Containers/MobilePush/Edit/index.js +2 -0
  125. package/v2Containers/MobilepushWrapper/index.js +3 -1
  126. package/v2Containers/Rcs/constants.js +32 -1
  127. package/v2Containers/Rcs/index.js +951 -873
  128. package/v2Containers/Rcs/index.scss +85 -6
  129. package/v2Containers/Rcs/messages.js +10 -1
  130. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  131. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
  132. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  133. package/v2Containers/Rcs/tests/index.test.js +41 -38
  134. package/v2Containers/Rcs/tests/mockData.js +38 -0
  135. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  136. package/v2Containers/Rcs/tests/utils.test.js +379 -1
  137. package/v2Containers/Rcs/utils.js +358 -10
  138. package/v2Containers/Sms/Create/index.js +83 -36
  139. package/v2Containers/Sms/Edit/index.js +2 -0
  140. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  141. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  142. package/v2Containers/SmsTrai/Create/index.js +9 -4
  143. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  144. package/v2Containers/SmsTrai/Edit/index.js +611 -128
  145. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  146. package/v2Containers/SmsTrai/Edit/messages.js +9 -4
  147. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
  148. package/v2Containers/SmsWrapper/index.js +39 -8
  149. package/v2Containers/TagList/index.js +47 -2
  150. package/v2Containers/TagList/messages.js +4 -0
  151. package/v2Containers/TagList/tests/TagList.test.js +122 -20
  152. package/v2Containers/TagList/tests/mockdata.js +17 -0
  153. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  154. package/v2Containers/Templates/_templates.scss +61 -2
  155. package/v2Containers/Templates/actions.js +11 -0
  156. package/v2Containers/Templates/constants.js +2 -0
  157. package/v2Containers/Templates/index.js +90 -40
  158. package/v2Containers/Templates/sagas.js +57 -12
  159. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  160. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  161. package/v2Containers/Templates/tests/sagas.test.js +193 -12
  162. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  163. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  164. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  165. package/v2Containers/TemplatesV2/index.js +86 -23
  166. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  167. package/v2Containers/Viber/index.js +5 -0
  168. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
  169. package/v2Containers/WebPush/Create/index.js +9 -1
  170. package/v2Containers/Whatsapp/index.js +8 -20
  171. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +598 -34
  172. package/v2Containers/Zalo/index.js +2 -0
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * DeliverySettings — summary row + CapSlideBox trigger for Test and Preview.
3
- * Rendered only for SMS, Email, WhatsApp. Uses cap-ui-library only.
3
+ * Rendered for SMS, Email, WhatsApp, RCS (ModifyDeliverySettings). RCS uses gsmSenderId + cdmaSenderId (SMS fallback).
4
4
  *
5
5
  * Reference: cap-campaigns-v2 DeliverySettingsV2 (summary + modify panel).
6
6
  */
7
7
 
8
- import React, { useState, useCallback } from "react";
8
+ import React, { useState, useCallback, useMemo } from "react";
9
9
  import PropTypes from "prop-types";
10
10
  import CapRow from "@capillarytech/cap-ui-library/CapRow";
11
11
  import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
@@ -22,6 +22,7 @@ import {
22
22
  SUMMARY_EMPTY_PLACEHOLDER,
23
23
  DELIVERY_SETTING_KEY_DOMAIN_ID,
24
24
  DELIVERY_SETTING_KEY_GSM_SENDER_ID,
25
+ DELIVERY_SETTING_KEY_CDMA_SENDER_ID,
25
26
  DELIVERY_SETTING_KEY_SENDER_EMAIL,
26
27
  DELIVERY_SETTING_KEY_SENDER_LABEL,
27
28
  DELIVERY_SETTING_KEY_SENDER_REPLY_TO,
@@ -35,7 +36,7 @@ const DeliverySettings = (props) => {
35
36
  const {
36
37
  channel,
37
38
  deliverySettings = {},
38
- senderDetailsOptions = [],
39
+ senderDetailsByChannel = {},
39
40
  wecrmAccounts = [],
40
41
  onSaveDeliverySettings,
41
42
  isLoadingSenderDetails,
@@ -43,6 +44,7 @@ const DeliverySettings = (props) => {
43
44
  smsTraiDltEnabled,
44
45
  registeredSenderIds,
45
46
  whatsappAccountFromForm,
47
+ isChannelSmsFallbackPreviewEnabled,
46
48
  } = props;
47
49
 
48
50
  const [isSlideBoxOpen, setSlideBoxOpen] = useState(false);
@@ -58,17 +60,68 @@ const DeliverySettings = (props) => {
58
60
  [onSaveDeliverySettings, closeSlideBox]
59
61
  );
60
62
 
63
+ const senderDetailsOptions = useMemo(
64
+ () => (senderDetailsByChannel[channel] || []),
65
+ [senderDetailsByChannel, channel],
66
+ );
67
+ const smsDomainsForRcs = useMemo(
68
+ () => (channel === CHANNELS.RCS ? (senderDetailsByChannel[CHANNELS.SMS] || []) : []),
69
+ [channel, senderDetailsByChannel],
70
+ );
71
+
61
72
  if (!CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel)) {
62
73
  return null;
63
74
  }
64
75
 
65
76
  const notConfiguredLabel = formatMessage(messages.notConfigured);
66
77
 
78
+ const getDisplayFromDomains = (domains, compositeValue) => {
79
+ if (!compositeValue || !domains?.length) return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
80
+ for (const senderDomain of domains) {
81
+ for (const gsmSenderRow of senderDomain.gsmSenders || []) {
82
+ const value = senderDomain.domainId != null && gsmSenderRow.value != null
83
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
84
+ : gsmSenderRow.value;
85
+ if (value === compositeValue && (senderDomain.domainName || gsmSenderRow.value)) {
86
+ return [senderDomain.domainName, gsmSenderRow.value].filter(Boolean).join(' · ');
87
+ }
88
+ }
89
+ }
90
+ return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
91
+ };
92
+
93
+ /** RCS summary: show sender ID only (no "domain · sender"). */
94
+ const getSenderIdOnlyFromComposite = (domains, compositeValue) => {
95
+ if (!compositeValue || !domains?.length) return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
96
+ for (const senderDomain of domains) {
97
+ for (const gsmSenderRow of senderDomain.gsmSenders || []) {
98
+ const value = senderDomain.domainId != null && gsmSenderRow.value != null
99
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
100
+ : gsmSenderRow.value;
101
+ if (value === compositeValue && gsmSenderRow.value != null) {
102
+ return String(gsmSenderRow.value);
103
+ }
104
+ }
105
+ }
106
+ return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
107
+ };
108
+
67
109
  const getSummaryText = () => {
68
110
  const empty = SUMMARY_EMPTY_PLACEHOLDER;
111
+ if (channel === CHANNELS.RCS) {
112
+ const rcsVal = get(deliverySettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID) || '';
113
+ const smsVal = get(deliverySettings, DELIVERY_SETTING_KEY_CDMA_SENDER_ID) || '';
114
+ const summaryRcs = {
115
+ rcsSenderId: getSenderIdOnlyFromComposite(senderDetailsOptions, rcsVal),
116
+ };
117
+ if (isChannelSmsFallbackPreviewEnabled) {
118
+ summaryRcs.smsFallbackSenderId = getSenderIdOnlyFromComposite(smsDomainsForRcs, smsVal);
119
+ }
120
+ return summaryRcs;
121
+ }
69
122
  if (channel === CHANNELS.SMS) {
70
123
  const domain = (senderDetailsOptions || []).find(
71
- (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
124
+ (senderDomain) => senderDomain.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
72
125
  );
73
126
  const domainName = domain?.domainName || empty;
74
127
  const senderId = get(deliverySettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID) || empty;
@@ -76,7 +129,7 @@ const DeliverySettings = (props) => {
76
129
  }
77
130
  if (channel === CHANNELS.EMAIL) {
78
131
  const domain = (senderDetailsOptions || []).find(
79
- (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
132
+ (senderDomain) => senderDomain.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
80
133
  );
81
134
  const emailDomain = domain?.domainName || empty;
82
135
  const senderEmail = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_EMAIL) || empty;
@@ -103,7 +156,12 @@ const DeliverySettings = (props) => {
103
156
 
104
157
  const summary = getSummaryText();
105
158
  let hasValues = false;
106
- if (channel === CHANNELS.SMS) {
159
+ if (channel === CHANNELS.RCS) {
160
+ hasValues = (summary.rcsSenderId && summary.rcsSenderId !== SUMMARY_EMPTY_PLACEHOLDER)
161
+ || (isChannelSmsFallbackPreviewEnabled
162
+ && summary.smsFallbackSenderId
163
+ && summary.smsFallbackSenderId !== SUMMARY_EMPTY_PLACEHOLDER);
164
+ } else if (channel === CHANNELS.SMS) {
107
165
  hasValues = summary.senderDomain !== SUMMARY_EMPTY_PLACEHOLDER
108
166
  || summary.senderId !== SUMMARY_EMPTY_PLACEHOLDER;
109
167
  } else if (channel === CHANNELS.EMAIL) {
@@ -122,6 +180,15 @@ const DeliverySettings = (props) => {
122
180
  const getSummaryObject = () => {
123
181
  if (!hasValues) return null;
124
182
  const label = (msg) => formatMessage(msg);
183
+ if (channel === CHANNELS.RCS) {
184
+ const rcsSummary = {
185
+ [label(messages.rcsSenderIdLabel)]: summary.rcsSenderId,
186
+ };
187
+ if (isChannelSmsFallbackPreviewEnabled) {
188
+ rcsSummary[label(messages.fallbackSmsSenderIdLabel)] = summary.smsFallbackSenderId;
189
+ }
190
+ return rcsSummary;
191
+ }
125
192
  if (channel === CHANNELS.SMS) {
126
193
  return {
127
194
  [label(messages.senderDomainSummary)]: summary.senderDomain,
@@ -165,7 +232,7 @@ const DeliverySettings = (props) => {
165
232
  Object.entries(summaryObject).map(([key, value]) => (
166
233
  <CapRow type="flex" key={key} className="delivery-settings__summary-entry">
167
234
  <CapLabel type="label1" className="delivery-settings__summary-key">{key}</CapLabel>
168
- <CapLabel type="label9">
235
+ <CapLabel type="label9" className="delivery-settings__summary-value">
169
236
  :
170
237
  {' '}
171
238
  {value}
@@ -194,6 +261,11 @@ const DeliverySettings = (props) => {
194
261
  channel={channel}
195
262
  deliverySettings={deliverySettings}
196
263
  senderDetailsOptions={senderDetailsOptions}
264
+ smsFallbackSenderDetailsOptions={
265
+ channel === CHANNELS.RCS && isChannelSmsFallbackPreviewEnabled
266
+ ? smsDomainsForRcs
267
+ : undefined
268
+ }
197
269
  wecrmAccounts={wecrmAccounts}
198
270
  onSaveDeliverySettings={handleSave}
199
271
  onClose={closeSlideBox}
@@ -213,9 +285,9 @@ const DeliverySettings = (props) => {
213
285
  DeliverySettings.propTypes = {
214
286
  channel: PropTypes.string.isRequired,
215
287
  deliverySettings: PropTypes.object,
216
- senderDetailsOptions: PropTypes.array,
288
+ senderDetailsByChannel: PropTypes.object,
217
289
  wecrmAccounts: PropTypes.array,
218
- onSaveDeliverySettings: PropTypes.func.isRequired,
290
+ onSaveDeliverySettings: PropTypes.func,
219
291
  isLoadingSenderDetails: PropTypes.bool,
220
292
  formatMessage: PropTypes.func,
221
293
  smsTraiDltEnabled: PropTypes.bool,
@@ -223,17 +295,20 @@ DeliverySettings.propTypes = {
223
295
  whatsappAccountFromForm: PropTypes.shape({
224
296
  accountName: PropTypes.string,
225
297
  }),
298
+ isChannelSmsFallbackPreviewEnabled: PropTypes.bool,
226
299
  };
227
300
 
228
301
  DeliverySettings.defaultProps = {
229
302
  deliverySettings: {},
230
- senderDetailsOptions: [],
303
+ senderDetailsByChannel: {},
231
304
  wecrmAccounts: [],
305
+ onSaveDeliverySettings: () => {},
232
306
  isLoadingSenderDetails: false,
233
307
  formatMessage: undefined,
234
308
  smsTraiDltEnabled: false,
235
309
  registeredSenderIds: [],
236
310
  whatsappAccountFromForm: undefined,
311
+ isChannelSmsFallbackPreviewEnabled: false,
237
312
  };
238
313
 
239
314
  export default DeliverySettings;
@@ -108,4 +108,34 @@ export default defineMessages({
108
108
  id: `${prefix}.disabledMessage`,
109
109
  defaultMessage: 'Message template selected belongs to this account',
110
110
  },
111
+ /** RCS: primary domain (slidebox) */
112
+ rcsDomainLabel: {
113
+ id: `${prefix}.rcsDomainLabel`,
114
+ defaultMessage: 'RCS domain:',
115
+ },
116
+ /** RCS: SMS fallback domain (slidebox) */
117
+ fallbackSmsDomainLabel: {
118
+ id: `${prefix}.fallbackSmsDomainLabel`,
119
+ defaultMessage: 'Fallback SMS domain:',
120
+ },
121
+ /** RCS: "RCS sender ID" */
122
+ rcsSenderIdLabel: {
123
+ id: `${prefix}.rcsSenderIdLabel`,
124
+ defaultMessage: 'RCS sender ID',
125
+ },
126
+ /** RCS: "Fallback SMS sender ID" */
127
+ fallbackSmsSenderIdLabel: {
128
+ id: `${prefix}.fallbackSmsSenderIdLabel`,
129
+ defaultMessage: 'Fallback SMS sender ID',
130
+ },
131
+ /** RCS: "Domain" (for domain · sender ID display) */
132
+ domainLabel: {
133
+ id: `${prefix}.domainLabel`,
134
+ defaultMessage: 'Domain',
135
+ },
136
+ /** RCS: placeholder for sender ID dropdown */
137
+ selectSenderId: {
138
+ id: `${prefix}.selectSenderId`,
139
+ defaultMessage: 'Select sender ID',
140
+ },
111
141
  });
@@ -9,29 +9,91 @@
9
9
 
10
10
  import get from 'lodash/get';
11
11
  import { CHANNELS } from '../../constants';
12
+ import { RCS_CONTACT_INFO_GSM_TYPE_KEYS } from '../constants';
12
13
 
14
+ /** Match API contactInfo.type (some envs use different casing). */
15
+ const typeMatches = (itemType, expectedKey) => {
16
+ if (!itemType || !expectedKey) return false;
17
+ const a = String(itemType).toLowerCase().replace(/-/g, '_');
18
+ const b = String(expectedKey).toLowerCase().replace(/-/g, '_');
19
+ return a === b;
20
+ };
21
+
22
+ /**
23
+ * Include row unless explicitly invalid — many APIs omit `valid`, which would
24
+ * otherwise filter out every sender (RCS/SMS lists empty in UI).
25
+ */
13
26
  const getSenderOptions = (contactInfo, key) =>
14
27
  (contactInfo || [])
15
- .filter((contactInfoItem) => contactInfoItem.type === key && contactInfoItem.valid)
28
+ .filter((contactInfoItem) => typeMatches(contactInfoItem.type, key) && contactInfoItem.valid !== false)
16
29
  .sort((contact) => (contact.default ? -1 : 0));
17
30
 
31
+ /** RCS APIs may label senders under several `contactInfo.type` keys — see `RCS_CONTACT_INFO_GSM_TYPE_KEYS`. */
32
+ const getRcsLikeGsmSenders = (contactInfo) => {
33
+ const seen = new Set();
34
+ const merged = [];
35
+ RCS_CONTACT_INFO_GSM_TYPE_KEYS.forEach((key) => {
36
+ getSenderOptions(contactInfo, key).forEach((row) => {
37
+ const v = row?.value;
38
+ // Skip empty/whitespace — they still pass `v != null` for "" and pollute RCS sender dropdowns.
39
+ if (v == null || String(v).trim() === '' || seen.has(v)) return;
40
+ seen.add(v);
41
+ merged.push(row);
42
+ });
43
+ });
44
+ return merged.sort((a, b) => (a.default ? -1 : 0) - (b.default ? -1 : 0));
45
+ };
46
+
47
+ /**
48
+ * Campaigns domainProperties may return { entity } or { result: { entity } } / { data: { entity } }.
49
+ */
50
+ function unwrapEntity(response) {
51
+ if (!response || typeof response !== 'object') return null;
52
+ if (response.entity != null) return response.entity;
53
+ const nested = get(response, 'result.entity') ?? get(response, 'data.entity');
54
+ if (nested != null) return nested;
55
+ if (response.entity === null) return null;
56
+ return response;
57
+ }
58
+
18
59
  /**
19
60
  * Parse raw API response for one channel into { domains: [...] }
20
- * @param {string} channel - SMS | EMAIL | WHATSAPP
61
+ * @param {string} channel - SMS | EMAIL | WHATSAPP | RCS
21
62
  * @param {Object} response - API response (e.g. { entity: { SMS: [...] } } or { entity: [...] })
22
63
  * @returns {{ domains: Array }} - domains array compatible with campaigns DeliverySettingsV2
23
64
  */
24
65
  export function parseSenderDetailsResponse(channel, response) {
25
- const entity = get(response, 'entity', response);
26
- if (!entity) {
66
+ const entity = unwrapEntity(response);
67
+ if (entity == null || entity === '') {
27
68
  return { domains: [] };
28
69
  }
29
70
 
30
- // Single-channel API: entity may be { [channel]: [...] } or direct array
31
- let channelSenderDetails = get(entity, channel, null);
71
+ // Normalize once: entity keys may be any casing (SMS/sms/rcs) but downstream branches use CHANNELS.* (uppercase).
72
+ const normalizedChannel =
73
+ channel == null || String(channel).trim() === ''
74
+ ? ''
75
+ : String(channel).trim().toUpperCase();
76
+
77
+ // Single-channel API: entity may be { [channel]: [...] } or direct array.
78
+ // Some responses use different casing (e.g. rcs vs RCS) or a single domain object instead of an array.
79
+ let channelSenderDetails =
80
+ get(entity, channel, null)
81
+ ?? (normalizedChannel ? get(entity, normalizedChannel, null) : null)
82
+ ?? (normalizedChannel ? get(entity, normalizedChannel.toLowerCase(), null) : null);
83
+
32
84
  if (channelSenderDetails == null && Array.isArray(entity)) {
33
85
  channelSenderDetails = entity;
34
86
  }
87
+
88
+ if (channelSenderDetails != null && !Array.isArray(channelSenderDetails)) {
89
+ const single = channelSenderDetails;
90
+ if (single && typeof single === 'object' && single.domainProperties) {
91
+ channelSenderDetails = [single];
92
+ } else {
93
+ return { domains: [] };
94
+ }
95
+ }
96
+
35
97
  if (!Array.isArray(channelSenderDetails)) {
36
98
  return { domains: [] };
37
99
  }
@@ -42,6 +104,7 @@ export function parseSenderDetailsResponse(channel, response) {
42
104
  const { id: dgmId, priority, domainProperties = {} } = element;
43
105
  const {
44
106
  domainName,
107
+ hostName,
45
108
  id = -1,
46
109
  contactInfo,
47
110
  connectionProperties: {
@@ -51,21 +114,25 @@ export function parseSenderDetailsResponse(channel, response) {
51
114
  } = {},
52
115
  } = domainProperties;
53
116
 
117
+ const resolvedDomainName = domainName || hostName;
118
+
54
119
  const domain = {
55
120
  dgmId,
56
- domainName,
121
+ domainName: resolvedDomainName,
57
122
  domainId: id,
58
123
  priority: priority != null ? priority : 0,
59
124
  };
60
125
 
61
- if ([CHANNELS.SMS, CHANNELS.WHATSAPP].includes(channel)) {
126
+ if ([CHANNELS.SMS, CHANNELS.WHATSAPP, CHANNELS.RCS].includes(normalizedChannel)) {
62
127
  domain.cdmaSenders = getSenderOptions(contactInfo, 'cdma_sender_id');
63
- domain.gsmSenders = getSenderOptions(contactInfo, 'gsm_sender_id');
128
+ domain.gsmSenders = normalizedChannel === CHANNELS.RCS
129
+ ? getRcsLikeGsmSenders(contactInfo)
130
+ : getSenderOptions(contactInfo, 'gsm_sender_id');
64
131
  domain.sourceAccountIdentifier =
65
132
  sourceAccountIdentifier || wabaId || userid || '';
66
133
  }
67
134
 
68
- if (channel === CHANNELS.EMAIL) {
135
+ if (normalizedChannel === CHANNELS.EMAIL) {
69
136
  domain.emailSenders = getSenderOptions(contactInfo, 'sender_id');
70
137
  domain.emailRepliers = getSenderOptions(contactInfo, 'reply_to_id');
71
138
  }
@@ -76,7 +143,8 @@ export function parseSenderDetailsResponse(channel, response) {
76
143
  // Sort by priority and dedupe by domainName (match campaigns behaviour)
77
144
  domains.sort((a, b) => (a.priority || 0) - (b.priority || 0));
78
145
  const deduped = domains.reduce((acc, domain) => {
79
- if (!acc.find((d) => d.domainName === domain.domainName)) {
146
+ const key = domain.domainName ?? domain.domainId;
147
+ if (!acc.find((existing) => (existing.domainName ?? existing.domainId) === key)) {
80
148
  acc.push(domain);
81
149
  }
82
150
  return acc;
@@ -6,12 +6,13 @@ import CapButton from '@capillarytech/cap-ui-library/CapButton';
6
6
  import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
7
7
  import CapStepsAccordian from '@capillarytech/cap-ui-library/CapStepsAccordian';
8
8
  import CapTreeSelect from '@capillarytech/cap-ui-library/CapTreeSelect';
9
+ import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
9
10
  import isEmpty from 'lodash/isEmpty';
10
11
  import messages from './messages';
11
12
  import DeliverySettings from './DeliverySettings';
12
13
  import { CHANNELS } from './constants';
13
14
 
14
- const CHANNELS_WITH_DELIVERY_SETTINGS = [CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP];
15
+ const CHANNELS_WITH_DELIVERY_SETTINGS = [CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP, CHANNELS.RCS];
15
16
 
16
17
  const SendTestMessage = ({
17
18
  isFetchingTestCustomers,
@@ -25,12 +26,13 @@ const SendTestMessage = ({
25
26
  isSendingTestMessage,
26
27
  formatMessage,
27
28
  deliverySettings,
28
- senderDetailsOptions,
29
+ senderDetailsByChannel = {},
29
30
  wecrmAccounts,
30
31
  onSaveDeliverySettings,
31
32
  isLoadingSenderDetails,
32
33
  smsTraiDltEnabled,
33
34
  registeredSenderIds,
35
+ isChannelSmsFallbackPreviewEnabled,
34
36
  }) => (
35
37
  <CapStepsAccordian
36
38
  showNumberSteps={false}
@@ -54,18 +56,20 @@ const SendTestMessage = ({
54
56
  value={selectedTestEntities}
55
57
  multiple
56
58
  placeholder={formatMessage(messages.testCustomersPlaceholder)}
59
+ getPopupContainer={(triggerNode) => triggerNode.parentNode}
57
60
  />
58
61
  {CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel) && (
59
62
  <DeliverySettings
60
63
  channel={channel}
61
64
  deliverySettings={deliverySettings || {}}
62
- senderDetailsOptions={senderDetailsOptions || []}
65
+ senderDetailsByChannel={senderDetailsByChannel}
63
66
  wecrmAccounts={wecrmAccounts || []}
64
67
  onSaveDeliverySettings={onSaveDeliverySettings}
65
68
  isLoadingSenderDetails={isLoadingSenderDetails}
66
69
  formatMessage={formatMessage}
67
70
  smsTraiDltEnabled={smsTraiDltEnabled}
68
71
  registeredSenderIds={registeredSenderIds}
72
+ isChannelSmsFallbackPreviewEnabled={isChannelSmsFallbackPreviewEnabled}
69
73
  whatsappAccountFromForm={
70
74
  channel === CHANNELS.WHATSAPP && formData?.accountName
71
75
  ? { accountName: formData.accountName }
@@ -95,24 +99,26 @@ SendTestMessage.propTypes = {
95
99
  isSendingTestMessage: PropTypes.bool.isRequired,
96
100
  formatMessage: PropTypes.func.isRequired,
97
101
  deliverySettings: PropTypes.object,
98
- senderDetailsOptions: PropTypes.array,
102
+ senderDetailsByChannel: PropTypes.object,
99
103
  wecrmAccounts: PropTypes.array,
100
104
  onSaveDeliverySettings: PropTypes.func,
101
105
  isLoadingSenderDetails: PropTypes.bool,
102
106
  smsTraiDltEnabled: PropTypes.bool,
103
107
  registeredSenderIds: PropTypes.array,
108
+ isChannelSmsFallbackPreviewEnabled: PropTypes.bool,
104
109
  };
105
110
 
106
111
  SendTestMessage.defaultProps = {
107
112
  formData: undefined,
108
113
  channel: undefined,
109
114
  deliverySettings: {},
110
- senderDetailsOptions: [],
115
+ senderDetailsByChannel: {},
111
116
  wecrmAccounts: [],
112
117
  onSaveDeliverySettings: undefined,
113
118
  isLoadingSenderDetails: false,
114
119
  smsTraiDltEnabled: false,
115
120
  registeredSenderIds: [],
121
+ isChannelSmsFallbackPreviewEnabled: false,
116
122
  };
117
123
 
118
124
  export default SendTestMessage;
@@ -11,7 +11,6 @@
11
11
  height: 100%;
12
12
  display: flex;
13
13
  flex-direction: column;
14
- background: $CAP_WHITE;
15
14
  overflow: hidden;
16
15
 
17
16
  // Preview Chrome wrapper (matches old TestAndPreviewSlidebox design)
@@ -62,7 +61,27 @@
62
61
  }
63
62
  }
64
63
  }
64
+
65
+ .unified-preview.unified-preview-rcs-tabs {
66
+ .ant-tabs-nav {
67
+ margin: 0;
68
+ padding: 0 $CAP_SPACE_16;
69
+ }
65
70
 
71
+ // Prevent white hover/active backgrounds from default antd styles
72
+ .ant-tabs-tab,
73
+ .ant-tabs-tab:hover,
74
+ .ant-tabs-tab-active {
75
+ background: transparent;
76
+ }
77
+
78
+ .ant-tabs-tab-btn,
79
+ .ant-tabs-tab-btn:hover,
80
+ .ant-tabs-tab-btn:active {
81
+ background: transparent;
82
+ }
83
+ }
84
+
66
85
  // Preview Content Container
67
86
  .preview-content-container {
68
87
  flex: 1;
@@ -21,8 +21,21 @@ import InAppPreviewContent from './InAppPreviewContent';
21
21
  import MobilePushPreviewContent from './MobilePushPreviewContent';
22
22
  import ViberPreviewContent from './ViberPreviewContent';
23
23
  import ZaloPreviewContent from './ZaloPreviewContent';
24
- import { CHANNELS, DESKTOP, TABLET, MOBILE, ANDROID, IOS } from '../constants';
24
+ import CapTab from '@capillarytech/cap-ui-library/CapTab';
25
+ import {
26
+ CHANNELS,
27
+ DESKTOP,
28
+ TABLET,
29
+ MOBILE,
30
+ ANDROID,
31
+ IOS,
32
+ PREVIEW_TAB_RCS,
33
+ PREVIEW_TAB_SMS_FALLBACK,
34
+ PREVIEW_TAB_KEYS,
35
+ RCS_SMS_FALLBACK_VAR_MAPPED_PROP,
36
+ } from '../constants';
25
37
  import messages from '../messages';
38
+ import { getFallbackResolvedContent } from '../../../utils/templateVarUtils';
26
39
  import './_unifiedPreview.scss';
27
40
 
28
41
  const UnifiedPreview = ({
@@ -38,7 +51,24 @@ const UnifiedPreview = ({
38
51
  lastModified,
39
52
  updatedByName,
40
53
  showHeader, // Default to true for Test and Preview flow, false for channel component previews
54
+ smsFallbackContent,
55
+ smsFallbackResolvedText,
56
+ activePreviewTab,
57
+ onPreviewTabChange,
41
58
  }) => {
59
+ const hasFallbackSmsTemplate = !!(smsFallbackContent?.templateContent || smsFallbackContent?.content);
60
+ const showRcsSmsFallbackTabs = channel === CHANNELS.RCS && hasFallbackSmsTemplate;
61
+ const rawFallbackTemplate = smsFallbackContent?.templateContent ?? smsFallbackContent?.content ?? '';
62
+ const rcsFallbackVarMapped = smsFallbackContent?.[RCS_SMS_FALLBACK_VAR_MAPPED_PROP] ?? {};
63
+ const hasRcsFallbackVarMapped = Object.keys(rcsFallbackVarMapped).length > 0;
64
+ // When no varmap is present, show raw template so {{tags}} remain visible in the preview.
65
+ // Only apply slot substitution when varmap entries exist or a resolved text is available.
66
+ const smsFallbackDisplayContent =
67
+ smsFallbackResolvedText != null && smsFallbackResolvedText !== ''
68
+ ? smsFallbackResolvedText
69
+ : hasRcsFallbackVarMapped
70
+ ? getFallbackResolvedContent(rawFallbackTemplate, rcsFallbackVarMapped)
71
+ : rawFallbackTemplate;
42
72
  /**
43
73
  * Render channel-specific preview content
44
74
  * For Phase 5, we'll render placeholders
@@ -124,6 +154,21 @@ const UnifiedPreview = ({
124
154
  case CHANNELS.RCS: {
125
155
  // RCS content is an object with rcsTitle, rcsDesc, rcsImageSrc, suggestions, etc.
126
156
  const rcsContent = typeof content === 'object' ? content : {};
157
+
158
+ if (showRcsSmsFallbackTabs && activePreviewTab === PREVIEW_TAB_SMS_FALLBACK) {
159
+ return (
160
+ <SmsPreviewContent
161
+ content={smsFallbackDisplayContent}
162
+ device={ANDROID}
163
+ isUpdating={isUpdating}
164
+ error={error}
165
+ formatMessage={formatMessage}
166
+ senderId={smsFallbackContent?.senderId}
167
+ showHeader={showHeader}
168
+ />
169
+ );
170
+ }
171
+
127
172
  return (
128
173
  <RcsPreviewContent
129
174
  content={rcsContent}
@@ -268,6 +313,79 @@ const UnifiedPreview = ({
268
313
  * PreviewHeader is shown only when showHeader is true (for Test and Preview flow)
269
314
  * Channel-specific content will be in separate files in future phases
270
315
  */
316
+ if (showRcsSmsFallbackTabs) {
317
+ const renderPane = ({ paneChannel, paneDevice, paneShowDeviceToggle, paneContent }) => (
318
+ <CapRow className="unified-preview-tab-pane">
319
+ {showHeader && (
320
+ <PreviewHeader
321
+ selectedCustomer={selectedCustomer}
322
+ device={paneDevice}
323
+ showDeviceToggle={paneShowDeviceToggle}
324
+ onDeviceChange={onDeviceChange}
325
+ channel={paneChannel}
326
+ />
327
+ )}
328
+
329
+ <CapRow className={`preview-content-container ${!showHeader ? 'preview-content-container-no-header' : ''}`}>
330
+ {paneContent}
331
+ </CapRow>
332
+
333
+
334
+ </CapRow>
335
+ );
336
+
337
+ return (
338
+ <CapRow className="unified-preview unified-preview-rcs-tabs">
339
+ <CapTab
340
+ activeKey={activePreviewTab}
341
+ onChange={onPreviewTabChange}
342
+ panes={[
343
+ {
344
+ tab: formatMessage(messages.rcsTab),
345
+ key: PREVIEW_TAB_RCS,
346
+ content: renderPane({
347
+ paneChannel: CHANNELS.RCS,
348
+ paneDevice: device,
349
+ paneShowDeviceToggle: showDeviceToggle,
350
+ paneContent: (
351
+ <RcsPreviewContent
352
+ content={typeof content === 'object' ? content : {}}
353
+ device={device}
354
+ isUpdating={isUpdating}
355
+ error={error}
356
+ formatMessage={formatMessage}
357
+ senderId={content?.senderId}
358
+ showHeader={showHeader}
359
+ />
360
+ ),
361
+ }),
362
+ },
363
+ {
364
+ tab: formatMessage(messages.smsFallbackTab),
365
+ key: PREVIEW_TAB_SMS_FALLBACK,
366
+ content: renderPane({
367
+ paneChannel: CHANNELS.SMS,
368
+ paneDevice: device,
369
+ paneShowDeviceToggle: showDeviceToggle,
370
+ paneContent: (
371
+ <SmsPreviewContent
372
+ content={smsFallbackDisplayContent}
373
+ device={device}
374
+ isUpdating={isUpdating}
375
+ error={error}
376
+ formatMessage={formatMessage}
377
+ senderId={smsFallbackContent?.senderId}
378
+ showHeader={showHeader}
379
+ />
380
+ ),
381
+ }),
382
+ },
383
+ ]}
384
+ />
385
+ </CapRow>
386
+ );
387
+ }
388
+
271
389
  return (
272
390
  <CapRow className="unified-preview">
273
391
  {/* PreviewHeader - shown only in Test and Preview flow, hidden in channel component previews */}
@@ -305,9 +423,7 @@ const UnifiedPreview = ({
305
423
  )}
306
424
  {updatedByName && (
307
425
  <span className="metadata-item">
308
- {formatMessage(messages.by)}
309
- {' '}
310
- {updatedByName}
426
+ {formatMessage(messages.byAuthor, { name: updatedByName })}
311
427
  </span>
312
428
  )}
313
429
  </CapRow>
@@ -348,6 +464,15 @@ UnifiedPreview.propTypes = {
348
464
 
349
465
  // Header display
350
466
  showHeader: PropTypes.bool, // Show PreviewHeader (true for Test and Preview flow, false for channel component previews)
467
+
468
+ // RCS: SMS fallback preview support (same shape as SmsFallback / RCS smsFallbackData)
469
+ smsFallbackContent: PropTypes.shape({
470
+ templateContent: PropTypes.string,
471
+ senderId: PropTypes.string,
472
+ templateName: PropTypes.string,
473
+ }),
474
+ activePreviewTab: PropTypes.oneOf(PREVIEW_TAB_KEYS),
475
+ onPreviewTabChange: PropTypes.func,
351
476
  };
352
477
 
353
478
  UnifiedPreview.defaultProps = {
@@ -360,6 +485,10 @@ UnifiedPreview.defaultProps = {
360
485
  lastModified: null,
361
486
  updatedByName: null,
362
487
  showHeader: true, // Default to true for Test and Preview flow
488
+ smsFallbackContent: null,
489
+ smsFallbackResolvedText: undefined,
490
+ activePreviewTab: PREVIEW_TAB_RCS,
491
+ onPreviewTabChange: () => {},
363
492
  };
364
493
 
365
494
  export default UnifiedPreview;