react-native-unit-components 1.14.0 → 1.15.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 (159) hide show
  1. package/ios/UNSharedServicesProvider/UNGlobalSnapshotProtectionService.swift +7 -4
  2. package/lib/commonjs/components/UNCardActionComponent/UNCardActionComponent.js +71 -0
  3. package/lib/commonjs/components/UNCardActionComponent/UNCardActionComponent.js.map +1 -0
  4. package/lib/commonjs/components/UNCardActionComponent/UNCardActionComponent.utils.js +22 -0
  5. package/lib/commonjs/components/UNCardActionComponent/UNCardActionComponent.utils.js.map +1 -0
  6. package/lib/commonjs/components/UNCardActionComponent/index.js +21 -0
  7. package/lib/commonjs/components/UNCardActionComponent/index.js.map +1 -0
  8. package/lib/commonjs/components/UNCardComponent/UNCardComponent.js +22 -0
  9. package/lib/commonjs/components/UNCardComponent/UNCardComponent.js.map +1 -1
  10. package/lib/commonjs/components/UNCardComponent/UNCardComponent.utils.js +2 -1
  11. package/lib/commonjs/components/UNCardComponent/UNCardComponent.utils.js.map +1 -1
  12. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.js +79 -0
  13. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.js.map +1 -0
  14. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.js +32 -0
  15. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.js.map +1 -0
  16. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/index.js +21 -0
  17. package/lib/commonjs/components/UNMultiFactorAuthenticationComponent/index.js.map +1 -0
  18. package/lib/commonjs/components/UNNextRepaymentComponent/UNNextRepaymentComponent.utils.js +1 -1
  19. package/lib/commonjs/components/UNNextRepaymentComponent/UNNextRepaymentComponent.utils.js.map +1 -1
  20. package/lib/commonjs/components/UNPayeeManagementComponent/UNPayeeManagementComponent.js +17 -0
  21. package/lib/commonjs/components/UNPayeeManagementComponent/UNPayeeManagementComponent.js.map +1 -1
  22. package/lib/commonjs/components/index.js +22 -0
  23. package/lib/commonjs/components/index.js.map +1 -1
  24. package/lib/commonjs/messages/webMessages/multiFactorAuthenticationMessage.js +11 -0
  25. package/lib/commonjs/messages/webMessages/multiFactorAuthenticationMessage.js.map +1 -0
  26. package/lib/commonjs/messages/webMessages/onLoadMessage.js +1 -0
  27. package/lib/commonjs/messages/webMessages/onLoadMessage.js.map +1 -1
  28. package/lib/commonjs/messages/webMessages/unitMessages.js +1 -0
  29. package/lib/commonjs/messages/webMessages/unitMessages.js.map +1 -1
  30. package/lib/commonjs/scripts/html/bodyScript.js +18 -5
  31. package/lib/commonjs/scripts/html/bodyScript.js.map +1 -1
  32. package/lib/commonjs/types/internal/webComponent.types.js +2 -0
  33. package/lib/commonjs/types/internal/webComponent.types.js.map +1 -1
  34. package/lib/commonjs/types/shared/multiFactorAuthentication.types.js +2 -0
  35. package/lib/commonjs/types/shared/multiFactorAuthentication.types.js.map +1 -0
  36. package/lib/commonjs/types/shared/payeeManagement.types.js.map +1 -1
  37. package/lib/commonjs/unitSdkManager/UnitSdk.constants.js +1 -1
  38. package/lib/commonjs/unitSdkManager/UnitSdkManager.js +5 -2
  39. package/lib/commonjs/unitSdkManager/UnitSdkManager.js.map +1 -1
  40. package/lib/commonjs/webComponent/WebComponent.js +11 -5
  41. package/lib/commonjs/webComponent/WebComponent.js.map +1 -1
  42. package/lib/commonjs/webComponent/WebComponent.utils.js +5 -1
  43. package/lib/commonjs/webComponent/WebComponent.utils.js.map +1 -1
  44. package/lib/commonjs/webComponent/html.js +2 -0
  45. package/lib/commonjs/webComponent/html.js.map +1 -1
  46. package/lib/module/components/UNCardActionComponent/UNCardActionComponent.js +63 -0
  47. package/lib/module/components/UNCardActionComponent/UNCardActionComponent.js.map +1 -0
  48. package/lib/module/components/UNCardActionComponent/UNCardActionComponent.utils.js +14 -0
  49. package/lib/module/components/UNCardActionComponent/UNCardActionComponent.utils.js.map +1 -0
  50. package/lib/module/components/UNCardActionComponent/index.js +2 -0
  51. package/lib/module/components/UNCardActionComponent/index.js.map +1 -0
  52. package/lib/module/components/UNCardComponent/UNCardComponent.js +22 -0
  53. package/lib/module/components/UNCardComponent/UNCardComponent.js.map +1 -1
  54. package/lib/module/components/UNCardComponent/UNCardComponent.utils.js +2 -1
  55. package/lib/module/components/UNCardComponent/UNCardComponent.utils.js.map +1 -1
  56. package/lib/module/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.js +71 -0
  57. package/lib/module/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.js.map +1 -0
  58. package/lib/module/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.js +24 -0
  59. package/lib/module/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.js.map +1 -0
  60. package/lib/module/components/UNMultiFactorAuthenticationComponent/index.js +2 -0
  61. package/lib/module/components/UNMultiFactorAuthenticationComponent/index.js.map +1 -0
  62. package/lib/module/components/UNNextRepaymentComponent/UNNextRepaymentComponent.utils.js +1 -1
  63. package/lib/module/components/UNNextRepaymentComponent/UNNextRepaymentComponent.utils.js.map +1 -1
  64. package/lib/module/components/UNPayeeManagementComponent/UNPayeeManagementComponent.js +17 -0
  65. package/lib/module/components/UNPayeeManagementComponent/UNPayeeManagementComponent.js.map +1 -1
  66. package/lib/module/components/index.js +2 -0
  67. package/lib/module/components/index.js.map +1 -1
  68. package/lib/module/messages/webMessages/multiFactorAuthenticationMessage.js +5 -0
  69. package/lib/module/messages/webMessages/multiFactorAuthenticationMessage.js.map +1 -0
  70. package/lib/module/messages/webMessages/onLoadMessage.js +1 -0
  71. package/lib/module/messages/webMessages/onLoadMessage.js.map +1 -1
  72. package/lib/module/messages/webMessages/unitMessages.js +1 -0
  73. package/lib/module/messages/webMessages/unitMessages.js.map +1 -1
  74. package/lib/module/scripts/html/bodyScript.js +17 -4
  75. package/lib/module/scripts/html/bodyScript.js.map +1 -1
  76. package/lib/module/types/internal/webComponent.types.js +2 -0
  77. package/lib/module/types/internal/webComponent.types.js.map +1 -1
  78. package/lib/module/types/shared/multiFactorAuthentication.types.js +2 -0
  79. package/lib/module/types/shared/multiFactorAuthentication.types.js.map +1 -0
  80. package/lib/module/types/shared/payeeManagement.types.js.map +1 -1
  81. package/lib/module/unitSdkManager/UnitSdk.constants.js +1 -1
  82. package/lib/module/unitSdkManager/UnitSdkManager.js +5 -2
  83. package/lib/module/unitSdkManager/UnitSdkManager.js.map +1 -1
  84. package/lib/module/webComponent/WebComponent.js +12 -6
  85. package/lib/module/webComponent/WebComponent.js.map +1 -1
  86. package/lib/module/webComponent/WebComponent.utils.js +3 -0
  87. package/lib/module/webComponent/WebComponent.utils.js.map +1 -1
  88. package/lib/module/webComponent/html.js +3 -1
  89. package/lib/module/webComponent/html.js.map +1 -1
  90. package/lib/typescript/src/components/UNCardActionComponent/UNCardActionComponent.d.ts +14 -0
  91. package/lib/typescript/src/components/UNCardActionComponent/UNCardActionComponent.d.ts.map +1 -0
  92. package/lib/typescript/src/components/UNCardActionComponent/UNCardActionComponent.utils.d.ts +4 -0
  93. package/lib/typescript/src/components/UNCardActionComponent/UNCardActionComponent.utils.d.ts.map +1 -0
  94. package/lib/typescript/src/components/UNCardActionComponent/index.d.ts +2 -0
  95. package/lib/typescript/src/components/UNCardActionComponent/index.d.ts.map +1 -0
  96. package/lib/typescript/src/components/UNCardComponent/UNCardComponent.d.ts +3 -1
  97. package/lib/typescript/src/components/UNCardComponent/UNCardComponent.d.ts.map +1 -1
  98. package/lib/typescript/src/components/UNCardComponent/UNCardComponent.utils.d.ts.map +1 -1
  99. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.d.ts +14 -0
  100. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.d.ts.map +1 -0
  101. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.d.ts +4 -0
  102. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.d.ts.map +1 -0
  103. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/index.d.ts +2 -0
  104. package/lib/typescript/src/components/UNMultiFactorAuthenticationComponent/index.d.ts.map +1 -0
  105. package/lib/typescript/src/components/UNPayeeManagementComponent/UNPayeeManagementComponent.d.ts +2 -1
  106. package/lib/typescript/src/components/UNPayeeManagementComponent/UNPayeeManagementComponent.d.ts.map +1 -1
  107. package/lib/typescript/src/components/index.d.ts +2 -0
  108. package/lib/typescript/src/components/index.d.ts.map +1 -1
  109. package/lib/typescript/src/messages/webMessages/index.d.ts +2 -1
  110. package/lib/typescript/src/messages/webMessages/index.d.ts.map +1 -1
  111. package/lib/typescript/src/messages/webMessages/multiFactorAuthenticationMessage.d.ts +4 -0
  112. package/lib/typescript/src/messages/webMessages/multiFactorAuthenticationMessage.d.ts.map +1 -0
  113. package/lib/typescript/src/messages/webMessages/onLoadMessage.d.ts +7 -3
  114. package/lib/typescript/src/messages/webMessages/onLoadMessage.d.ts.map +1 -1
  115. package/lib/typescript/src/messages/webMessages/unitMessages.d.ts +11 -1
  116. package/lib/typescript/src/messages/webMessages/unitMessages.d.ts.map +1 -1
  117. package/lib/typescript/src/scripts/html/bodyScript.d.ts +1 -0
  118. package/lib/typescript/src/scripts/html/bodyScript.d.ts.map +1 -1
  119. package/lib/typescript/src/slices/SharedEventsSlice.d.ts +2 -2
  120. package/lib/typescript/src/slices/SharedEventsSlice.d.ts.map +1 -1
  121. package/lib/typescript/src/store/store.d.ts +2 -2
  122. package/lib/typescript/src/types/internal/webComponent.types.d.ts +3 -1
  123. package/lib/typescript/src/types/internal/webComponent.types.d.ts.map +1 -1
  124. package/lib/typescript/src/types/shared/multiFactorAuthentication.types.d.ts +15 -0
  125. package/lib/typescript/src/types/shared/multiFactorAuthentication.types.d.ts.map +1 -0
  126. package/lib/typescript/src/types/shared/payeeManagement.types.d.ts +32 -0
  127. package/lib/typescript/src/types/shared/payeeManagement.types.d.ts.map +1 -1
  128. package/lib/typescript/src/unitSdkManager/UnitSdkManager.d.ts +1 -1
  129. package/lib/typescript/src/unitSdkManager/UnitSdkManager.d.ts.map +1 -1
  130. package/lib/typescript/src/webComponent/WebComponent.d.ts.map +1 -1
  131. package/lib/typescript/src/webComponent/WebComponent.utils.d.ts +3 -1
  132. package/lib/typescript/src/webComponent/WebComponent.utils.d.ts.map +1 -1
  133. package/lib/typescript/src/webComponent/html.d.ts.map +1 -1
  134. package/package.json +1 -1
  135. package/src/components/UNCardActionComponent/UNCardActionComponent.tsx +81 -0
  136. package/src/components/UNCardActionComponent/UNCardActionComponent.utils.ts +16 -0
  137. package/src/components/UNCardActionComponent/index.ts +1 -0
  138. package/src/components/UNCardComponent/UNCardComponent.tsx +25 -1
  139. package/src/components/UNCardComponent/UNCardComponent.utils.ts +2 -1
  140. package/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.tsx +86 -0
  141. package/src/components/UNMultiFactorAuthenticationComponent/UNMultiFactorAuthenticationComponent.utils.ts +27 -0
  142. package/src/components/UNMultiFactorAuthenticationComponent/index.ts +1 -0
  143. package/src/components/UNNextRepaymentComponent/UNNextRepaymentComponent.utils.ts +1 -1
  144. package/src/components/UNPayeeManagementComponent/UNPayeeManagementComponent.tsx +23 -1
  145. package/src/components/index.ts +2 -0
  146. package/src/messages/webMessages/index.ts +2 -0
  147. package/src/messages/webMessages/multiFactorAuthenticationMessage.ts +3 -0
  148. package/src/messages/webMessages/onLoadMessage.ts +8 -1
  149. package/src/messages/webMessages/unitMessages.ts +14 -2
  150. package/src/scripts/html/bodyScript.ts +18 -4
  151. package/src/slices/SharedEventsSlice.ts +2 -2
  152. package/src/types/internal/webComponent.types.ts +2 -0
  153. package/src/types/shared/multiFactorAuthentication.types.ts +17 -0
  154. package/src/types/shared/payeeManagement.types.ts +31 -0
  155. package/src/unitSdkManager/UnitSdk.constants.ts +1 -1
  156. package/src/unitSdkManager/UnitSdkManager.ts +6 -4
  157. package/src/webComponent/WebComponent.tsx +14 -6
  158. package/src/webComponent/WebComponent.utils.ts +6 -1
  159. package/src/webComponent/html.ts +4 -1
@@ -0,0 +1,16 @@
1
+ import { LISTENERS } from '../../scripts/html/bodyScript';
2
+ import { UNCardActionComponentProps } from './UNCardActionComponent';
3
+
4
+ export const getCardActionParams = (props: UNCardActionComponentProps) => {
5
+ return `
6
+ card-id="${props.cardId}"
7
+ customer-token="${props.customerToken}"
8
+ action="${props.action}"
9
+ `;
10
+ };
11
+
12
+ export const getCardActionScript = () => {
13
+ return `
14
+ ${LISTENERS.requestRefresh}
15
+ `;
16
+ };
@@ -0,0 +1 @@
1
+ export { default as UNCardActionComponent, UNCardActionComponentProps } from './UNCardActionComponent';
@@ -12,7 +12,7 @@ import {
12
12
  injectRequestCardActionScript,
13
13
  injectRequestShowSensitiveDataScript, injectRequestHideSensitiveDataScript,
14
14
  } from './UNCardComponent.utils';
15
- import type { UNOnLoadResponse, UNCardData, UNError, UNCardMenuAction } from '../../types/shared';
15
+ import { UNOnLoadResponse, UNCardData, UNError, UNCardMenuAction } from '../../types/shared';
16
16
  import { CardMessage } from '../../messages/webMessages/cardMessage';
17
17
  import { NativeModules } from 'react-native';
18
18
  import { RESPONSE_KEYS, UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
@@ -51,6 +51,8 @@ export interface UNCardComponentProps {
51
51
  onLoad?: (response: UNOnLoadResponse<UNCardData>) => void;
52
52
  onStatusChanged?: (card: UNCardData) => void;
53
53
  onCardActivated?: (card: UNCardData) => void;
54
+ onAction?: (action: UNCardMenuAction) => void;
55
+ onActionsMenuClicked?: () => void;
54
56
  pushProvisioningModule?: typeof NativeModules;
55
57
  }
56
58
 
@@ -142,6 +144,8 @@ const UNCardComponent = React.forwardRef<CardRef, UNCardComponentProps>(function
142
144
  } as SlotRendering;
143
145
 
144
146
  dispatch(setEvent({ key: BottomSheetNativeMessage.REQUEST_RENDERING, data }));
147
+
148
+ sendActionCallbackIfNeeded(slotData.requestRenderingEvent);
145
149
  break;
146
150
  }
147
151
  case PageMessage.PAGE_HEIGHT:
@@ -153,6 +157,26 @@ const UNCardComponent = React.forwardRef<CardRef, UNCardComponentProps>(function
153
157
  }
154
158
  };
155
159
 
160
+ const sendActionCallbackIfNeeded = (requestRenderingEvent: RequestRenderingEvent) => {
161
+ switch (requestRenderingEvent.data.nativeComponentName) {
162
+ case WebComponentType.cardMenu:
163
+ props.onActionsMenuClicked && props.onActionsMenuClicked();
164
+ break;
165
+ case WebComponentType.cardAction: {
166
+ // Find the relevant action from the native component
167
+ const actionMatch = requestRenderingEvent.data.nativeComponent.match(/action=([^\s]+)/);
168
+ if (actionMatch && props.onAction) {
169
+ const actionString = actionMatch[1] as string;
170
+
171
+ // Check if the actionString matches any value in the UNCardMenuAction enum
172
+ if (Object.values(UNCardMenuAction).includes(actionString as UNCardMenuAction)) {
173
+ props.onAction(actionString as UNCardMenuAction);
174
+ }
175
+ }
176
+ }
177
+ }
178
+ };
179
+
156
180
  useEffect(() => {
157
181
  UnitSDK.setCustomerToken(props.customerToken);
158
182
  }, [props.customerToken]);
@@ -4,13 +4,14 @@ import type { UNCardComponentProps } from './UNCardComponent';
4
4
  import type { RequestRefreshEvent } from '../../messages/webMessages/unitMessages';
5
5
  import type { UNCardMenuAction } from '../../types/shared';
6
6
  import { WebComponentType } from '../../types/internal/webComponent.types';
7
+ import { UnitSDK } from '../../unitSdkManager/UnitSdkManager';
7
8
 
8
9
  export const getCardParams = (props: UNCardComponentProps) => {
9
10
  const menuItemsParam = props.menuItems ? `menu-items="${props.menuItems.join()}"` : '';
10
11
  return `
11
12
  card-id="${props.cardId}"
12
13
  customer-token="${props.customerToken}"
13
- enable-mobile-wallet="${!!props.pushProvisioningModule}"
14
+ enable-mobile-wallet="${!!(props.pushProvisioningModule || UnitSDK.getPushProvisionModule())}"
14
15
  hide-actions-menu-button="${props.hideActionsMenuButton || false}"
15
16
  hide-card-title="${props.hideCardTitle || false}"
16
17
  hide-sensitive-data-button="${props.hideSensitiveDataButton || false}"
@@ -0,0 +1,86 @@
1
+ import React, { useState } from 'react';
2
+ import { UNBaseView } from '../../nativeComponents/UNBaseView';
3
+ import { WebComponent } from '../../webComponent/WebComponent';
4
+ import { PresentationMode, WebComponentType } from '../../types/internal/webComponent.types';
5
+ import { withReduxStore } from '../../helpers/store/helpers';
6
+ import { getMultiFactorAuthenticationParams, getMultiFactorAuthenticationScript } from './UNMultiFactorAuthenticationComponent.utils';
7
+ import type { WebViewMessage } from '../../messages/webMessages';
8
+ import { HeightEvent, PageMessage } from '../../messages/webMessages/pageMessage';
9
+ import { MultiFactorAuthenticationFinishedEvent, UnitMessage } from '../../messages/webMessages/unitMessages';
10
+ import { UNError, UNOnLoadResponse } from '../../types/shared';
11
+ import { RESPONSE_KEYS, UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
12
+ import { MultiFactorAuthenticationMessage } from '../../messages/webMessages/multiFactorAuthenticationMessage';
13
+ import { UNCustomerTokenVerification, UNMultiFactorAuthenticationFinished } from '../../types/shared/multiFactorAuthentication.types';
14
+
15
+ export interface UNMultiFactorAuthenticationComponentProps {
16
+ // inputs
17
+ customerToken: string;
18
+
19
+ // ui
20
+ theme?: string;
21
+ language?: string;
22
+
23
+ // callbacks
24
+ onLoad?: (response: UNOnLoadResponse<undefined>) => void
25
+ onVerificationTokenCreated?: (data: UNCustomerTokenVerification) => void
26
+ onAuthenticationFinished?: (data: UNMultiFactorAuthenticationFinished) => void
27
+ }
28
+
29
+ const UNMultiFactorAuthenticationComponent = (props: UNMultiFactorAuthenticationComponentProps) => {
30
+ const [height, setHeight] = useState<number>(0);
31
+ const [presentationMode, setPresentationMode] = useState<PresentationMode>(PresentationMode.Inherit);
32
+
33
+ const handleUnitOnLoad = (response: UnitOnLoadResponseEvent) => {
34
+ if (!props.onLoad) {
35
+ return;
36
+ }
37
+
38
+ if (RESPONSE_KEYS.errors in response) {
39
+ props.onLoad(response as UNError);
40
+ return;
41
+ }
42
+
43
+ props.onLoad({ data: undefined });
44
+ };
45
+
46
+ const handleWebViewMessage = (message: WebViewMessage) => {
47
+ if (!message || !message.details) return;
48
+
49
+ switch (message.type) {
50
+ case UnitMessage.UNIT_ON_LOAD:
51
+ handleUnitOnLoad(message.details as UnitOnLoadResponseEvent);
52
+ break;
53
+ case PageMessage.PAGE_HEIGHT: {
54
+ const currentHeight = (message.details as HeightEvent).height;
55
+ setHeight(currentHeight);
56
+ if (presentationMode === PresentationMode.Inherit && currentHeight === 0) {
57
+ setPresentationMode(PresentationMode.Default);
58
+ }
59
+ break;
60
+ }
61
+ case MultiFactorAuthenticationMessage.UNIT_MFA_VERIFICATION_TOKEN_CREATED:
62
+ props.onVerificationTokenCreated && props.onVerificationTokenCreated(message.details as UNCustomerTokenVerification);
63
+ break;
64
+ case UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED: {
65
+ const data = JSON.parse((message.details as MultiFactorAuthenticationFinishedEvent).unitVerifiedCustomerTokenString);
66
+ props.onAuthenticationFinished && props.onAuthenticationFinished(data as UNMultiFactorAuthenticationFinished);
67
+ break;
68
+ }
69
+ }
70
+ };
71
+
72
+ const style = presentationMode === PresentationMode.Inherit ? { flex: 1 } : { height: height };
73
+ return <UNBaseView style={style} onLoadError={handleUnitOnLoad}>
74
+ <WebComponent
75
+ type={WebComponentType.multiFactorAuthentication}
76
+ presentationMode={PresentationMode.Inherit}
77
+ params={getMultiFactorAuthenticationParams(props)}
78
+ script={getMultiFactorAuthenticationScript()}
79
+ onMessage={(message: WebViewMessage) => handleWebViewMessage(message)}
80
+ theme={props.theme}
81
+ language={props.language}
82
+ />
83
+ </UNBaseView>;
84
+ };
85
+
86
+ export default withReduxStore<UNMultiFactorAuthenticationComponentProps>(UNMultiFactorAuthenticationComponent);
@@ -0,0 +1,27 @@
1
+ import { MultiFactorAuthenticationMessage } from '../../messages/webMessages/multiFactorAuthenticationMessage';
2
+ import { UNMultiFactorAuthenticationComponentProps } from './UNMultiFactorAuthenticationComponent';
3
+
4
+ export const getMultiFactorAuthenticationParams = (props: UNMultiFactorAuthenticationComponentProps) => {
5
+ return `
6
+ customer-token="${props.customerToken}"
7
+ `;
8
+ };
9
+
10
+ const MULTI_FACTOR_AUTHENTICATION_LISTENERS = {
11
+ verificationTokenCreated: `
12
+ window.addEventListener("${MultiFactorAuthenticationMessage.UNIT_MFA_VERIFICATION_TOKEN_CREATED}", (e) => {
13
+ const response = e.detail
14
+ response.then((data) => {
15
+ postMessageToSDK({ type: "${MultiFactorAuthenticationMessage.UNIT_MFA_VERIFICATION_TOKEN_CREATED}", details: data.data })
16
+ }).catch((e) => {
17
+ console.log(e)
18
+ })
19
+ });
20
+ `
21
+ };
22
+
23
+ export const getMultiFactorAuthenticationScript = () => {
24
+ return `
25
+ ${MULTI_FACTOR_AUTHENTICATION_LISTENERS.verificationTokenCreated}
26
+ `;
27
+ };
@@ -0,0 +1 @@
1
+ export { default as UNMultiFactorAuthenticationComponent, UNMultiFactorAuthenticationComponentProps } from './UNMultiFactorAuthenticationComponent';
@@ -5,6 +5,6 @@ export const getNextRepaymentParams = (props: UNNextRepaymentComponentProps) =>
5
5
  return `
6
6
  customer-token="${props.customerToken}"
7
7
  account-id="${props.accountId}"
8
- hide-actions-menu-button="${props.hideTitle || false}"
8
+ hide-title="${props.hideTitle || false}"
9
9
  `;
10
10
  };
@@ -8,7 +8,7 @@ import { WebComponent } from '../../webComponent/WebComponent';
8
8
  import type { WebViewMessage } from '../../messages/webMessages';
9
9
  import { PresentationMode, WebComponentType } from '../../types/internal/webComponent.types';
10
10
  import { withReduxStore } from '../../helpers/store/helpers';
11
- import { UNPayeeConnectedAccount, UNPayeeCounterparty, UNPayeeManagementComponentPaginationType, UNPayeeManagementMenuItem, UNPlaidAccountFilter } from '../../types/shared';
11
+ import { UNError, UNOnLoadResponse, UNPayeeConnectedAccount, UNPayeeCounterparty, UNPayeeManagementComponentPaginationType, UNPayeeManagementMenuItem, UNPlaidAccountFilter } from '../../types/shared';
12
12
  import { getPayeeParams, getPayeeManagementScript, injectRefreshEventIfNeeded, injectUnitPlaidResponse, injectUnitOpenPlaid, injectUnitPlaidExit } from './UNPayeeManagementComponent.utils';
13
13
  import { BottomSheetRenderingType, BottomSheetSlotData, SlotRendering } from '../../types/internal/bottomSheet.types';
14
14
  import { RequestRenderingEvent } from '../../messages/webMessages/unitMessages';
@@ -20,6 +20,7 @@ import { LinkSuccess, openLink } from 'react-native-plaid-link-sdk';
20
20
  import { OpenPlaidEvent, PlaidMessage } from '../../messages/webMessages/plaidMessages';
21
21
  import { PayeeConnectedAccountEvent, PayeeCounterpartyEvent, PayeeManagementMessage, PayeeMicroDepositeConnectionEvent } from '../../messages/webMessages/payeeManagementMessage';
22
22
  import { UNBaseView } from '../../nativeComponents/UNBaseView';
23
+ import { RESPONSE_KEYS, UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
23
24
 
24
25
  export interface UNPayeeManagementComponentProps {
25
26
  // inputs
@@ -45,6 +46,7 @@ export interface UNPayeeManagementComponentProps {
45
46
  plaidLinkCustomizationName?: string;
46
47
 
47
48
  // events
49
+ onLoad?: (response: UNOnLoadResponse<[UNPayeeCounterparty]>) => void;
48
50
  onCounterpartyCreated?: (counterparty: UNPayeeCounterparty) => void;
49
51
  onCounterpartyDeleted?: (counterparty: UNPayeeCounterparty) => void;
50
52
 
@@ -103,6 +105,25 @@ const UNPayeeManagementComponent = (props: UNPayeeManagementComponentProps) => {
103
105
  }
104
106
  };
105
107
 
108
+ const handleUnitOnLoad = (response: UnitOnLoadResponseEvent) => {
109
+ if (!props.onLoad) {
110
+ return;
111
+ }
112
+
113
+ if (RESPONSE_KEYS.errors in response) {
114
+ props.onLoad(response as UNError);
115
+ return;
116
+ }
117
+
118
+ if (RESPONSE_KEYS.counterpartiesResult in response) {
119
+ props.onLoad(response[RESPONSE_KEYS.counterpartiesResult] as UNOnLoadResponse<[UNPayeeCounterparty]>);
120
+ return;
121
+ }
122
+
123
+ console.error('On Load Error: unexpected response type');
124
+ return;
125
+ };
126
+
106
127
  const handleMessage = (message: WebViewMessage) => {
107
128
  switch (message.type) {
108
129
  case UnitMessage.UNIT_REQUEST_RENDERING: {
@@ -111,6 +132,7 @@ const UNPayeeManagementComponent = (props: UNPayeeManagementComponentProps) => {
111
132
  break;
112
133
  }
113
134
  case UnitMessage.UNIT_ON_LOAD: {
135
+ handleUnitOnLoad(message.details as UnitOnLoadResponseEvent);
114
136
  break;
115
137
  }
116
138
  case PayeeManagementMessage.UNIT_CONNECTED_ACCOUNT_CREATED: {
@@ -13,3 +13,5 @@ export * from './UNNextRepaymentComponent';
13
13
  export * from './UNWhiteLabelAppComponent';
14
14
  export * from './UNPayeeManagementComponent';
15
15
  export * from './UNWirePaymentComponent';
16
+ export * from './UNMultiFactorAuthenticationComponent';
17
+ export * from './UNCardActionComponent';
@@ -12,6 +12,7 @@ import type { MultipleCardsEvent, MultipleCardsMessage } from './multipleCardsMe
12
12
  import { FundAccountPaymentEvent } from './fundAccountPaymentMessage';
13
13
  import { PlaidEvent, PlaidMessage } from './plaidMessages';
14
14
  import { PayeeManagementMessage, PayeeManagementEvent } from './payeeManagementMessage';
15
+ import { MultiFactorAuthenticationMessage } from './multiFactorAuthenticationMessage';
15
16
 
16
17
  export type WebViewMessageType =
17
18
  | PageMessage
@@ -24,6 +25,7 @@ export type WebViewMessageType =
24
25
  | ActivityMessage
25
26
  | PlaidMessage
26
27
  | PayeeManagementMessage
28
+ | MultiFactorAuthenticationMessage
27
29
 
28
30
  type WebViewEvent =
29
31
  | PageEvent
@@ -0,0 +1,3 @@
1
+ export enum MultiFactorAuthenticationMessage {
2
+ UNIT_MFA_VERIFICATION_TOKEN_CREATED = 'unitMultiFactorAuthVerificationTokenCreated'
3
+ }
@@ -4,6 +4,7 @@ import type {
4
4
  UNCardData,
5
5
  UNError,
6
6
  UNOnLoadResponseData,
7
+ UNPayeeCounterparty
7
8
  } from '../../types/shared';
8
9
  import type { UNAuthorizationData } from '../../types/shared/authorization.types';
9
10
  import type { UNTransactionData } from '../../types/shared/transactions.types';
@@ -19,7 +20,8 @@ export enum RESPONSE_KEYS {
19
20
  authorizations = 'authorizationsResult',
20
21
  repayment = 'repaymentResult',
21
22
  astraExternalCard = 'astraCardsResult',
22
- accountCards = 'accountCardsResult'
23
+ accountCards = 'accountCardsResult',
24
+ counterpartiesResult = 'counterpartiesResult'
23
25
  }
24
26
 
25
27
  export type CardsOnLoadResponse = {
@@ -54,6 +56,10 @@ export type FundAccountPaymentOnLoadResponse = {
54
56
  [RESPONSE_KEYS.accountCards]?: UNOnLoadResponseData<[UNCardData]>
55
57
  }
56
58
 
59
+ export type PayeeManagementOnLoadResponse = {
60
+ [RESPONSE_KEYS.counterpartiesResult]: UNOnLoadResponseData<[UNPayeeCounterparty]>
61
+ }
62
+
57
63
  export type UnitOnLoadResponseSuccessData =
58
64
  | CardOnLoadResponse
59
65
  | CardsOnLoadResponse
@@ -62,6 +68,7 @@ export type UnitOnLoadResponseSuccessData =
62
68
  | AccountOnLoadResponse
63
69
  | ActivityOnLoadResponse
64
70
  | FundAccountPaymentOnLoadResponse
71
+ | PayeeManagementOnLoadResponse
65
72
 
66
73
  export type UnitOnLoadResponseEvent =
67
74
  | UNError
@@ -13,11 +13,12 @@ export enum UnitMessage {
13
13
  UNIT_REQUEST_LEFT_TO_SPEND_DETAILS = 'unitRequestLeftToSpendDetails',
14
14
  UNIT_MULTI_FACTOR_AUTH_FINISHED = 'unitMultiFactorAuthFinished',
15
15
  UNIT_WHITE_LABEL_APP_ON_LOAD = 'unitWhiteLabelAppOnLoad',
16
- UNIT_UNAUTHORIZED_TOKEN = 'unitUnauthorizedToken'
16
+ UNIT_UNAUTHORIZED_TOKEN = 'unitUnauthorizedToken',
17
+ UNIT_EVENT_TO_CONTINUE = 'unitEventToContinue'
17
18
  }
18
19
 
19
20
  export enum UnitRequestRefreshEventTypes {
20
- REQUEST_REFRESH_EVENT = 'requestRefreshEvent'
21
+ REQUEST_REFRESH_EVENT = 'requestRefreshEvent'
21
22
  }
22
23
 
23
24
  export interface RequestRenderingEvent {
@@ -38,6 +39,12 @@ export interface RequestRefreshEvent {
38
39
  resourceId?: string;
39
40
  }
40
41
 
42
+ export interface MultiFactorAuthenticationFinishedEvent {
43
+ unitVerifiedCustomerTokenString: string;
44
+ parentInstanceId?: string;
45
+ eventToContinue?: string;
46
+ }
47
+
41
48
  export interface RequestOpenLinkEvent {
42
49
  href: string;
43
50
  target: string;
@@ -51,6 +58,11 @@ export interface RequestDownloadEvent {
51
58
  fileName: string;
52
59
  }
53
60
 
61
+ export interface EventToContinueEvent {
62
+ parentInstanceId?: string;
63
+ eventToContinue?: string;
64
+ }
65
+
54
66
  export interface PlaidTokenCreatedEvent {
55
67
  linkToken: PlaidLinkTokenData;
56
68
  }
@@ -146,12 +146,19 @@ export const LISTENERS = {
146
146
  `,
147
147
  unitMultiFactorAuthFinished: `
148
148
  window.addEventListener("${UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED}", async (e) => {
149
- const response = await event.detail.response;
150
- const data = JSON.stringify({
149
+ const response = await e.detail.response;
150
+ const unitVerifiedCustomerToken = {
151
151
  token: response.data.attributes.token,
152
152
  expiration: new Date().getTime() + response.data.attributes.expiresIn * 1000,
153
- });
154
- window.UnitStore["unitVerifiedCustomerToken"] = data;
153
+ };
154
+ const unitVerifiedCustomerTokenString = JSON.stringify(unitVerifiedCustomerToken);
155
+ window.UnitStore["unitVerifiedCustomerToken"] = unitVerifiedCustomerTokenString;
156
+
157
+ const data = {
158
+ unitVerifiedCustomerTokenString,
159
+ parentInstanceId: e.detail.parentInstanceId,
160
+ eventToContinue: e.detail.eventToContinue
161
+ }
155
162
 
156
163
  postMessageToSDK({ type: "${UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED}", details: data })
157
164
  });
@@ -241,6 +248,13 @@ export const DISPATCH_RENDERING_EVENT = `
241
248
  }
242
249
  `;
243
250
 
251
+ export const DISPATCH_EVENT_TO_CONTINUE = `
252
+ const dispatchEventToContinue = (details) => {
253
+ const event = new CustomEvent("${UnitMessage.UNIT_EVENT_TO_CONTINUE}",{ detail: JSON.parse(details) })
254
+ window.dispatchEvent(event)
255
+ }
256
+ `;
257
+
244
258
  export const DISPATCH_REQUEST_REFRESH = `
245
259
  const dispatchRefreshEvent = (details) => {
246
260
  let event;
@@ -4,7 +4,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
4
4
  import type { RootState } from '../store';
5
5
  import type { UNAccountData, UNCardData, UNPayeeCounterparty } from '../types/shared';
6
6
  import type { ActivityFiltersChangedEvent } from '../messages/webMessages/activityMessage';
7
- import type { RequestRefreshEvent } from '../messages/webMessages/unitMessages';
7
+ import type { MultiFactorAuthenticationFinishedEvent, RequestRefreshEvent } from '../messages/webMessages/unitMessages';
8
8
  import type { BottomSheetNativeMessage } from '../messages/nativeMessages/bottomSheetMessage';
9
9
  import type { CardMessage } from '../messages/webMessages/cardMessage';
10
10
  import type { AccountMessage } from '../messages/webMessages/accountMessage';
@@ -60,7 +60,7 @@ type RequestRefreshEventState = {
60
60
 
61
61
  type MultiFactorAuthFinishedEventState = {
62
62
  key: UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED,
63
- data: string
63
+ data: MultiFactorAuthenticationFinishedEvent
64
64
  }
65
65
 
66
66
  type ComponentHeightEventState = {
@@ -15,6 +15,8 @@ export enum WebComponentType {
15
15
  payeeManagement = 'unit-elements-payee-management',
16
16
  wirePayment = 'unit-elements-wire-payment',
17
17
  whiteLabelApp = 'unit-elements-white-label-app',
18
+ multiFactorAuthentication = 'unit-elements-multi-factor-authentication',
19
+ cardMenu = 'unit-elements-card-menu'
18
20
  }
19
21
 
20
22
  export enum PresentationMode {
@@ -0,0 +1,17 @@
1
+ export interface UNMultiFactorVerification {
2
+ type: string
3
+
4
+ attributes: {
5
+ verificationToken: string
6
+ phoneLast4Digits?: string
7
+ }
8
+ }
9
+
10
+ export interface UNCustomerTokenVerification extends UNMultiFactorVerification {
11
+ type: 'customerTokenVerification'
12
+ }
13
+
14
+ export type UNMultiFactorAuthenticationFinished = {
15
+ token: string
16
+ expiresIn: number
17
+ }
@@ -35,6 +35,14 @@ export type UNPayeeCounterparty = {
35
35
  type: UNCounterpartyType
36
36
  permissions: UNCounterpartyPermission
37
37
  tags?: {[key: string]: string}
38
+ },
39
+ relationships: {
40
+ customer: {
41
+ data: {
42
+ type: 'customer'
43
+ id: number
44
+ }
45
+ }
38
46
  }
39
47
  }
40
48
 
@@ -47,3 +55,26 @@ export enum UNPayeeManagementComponentPaginationType {
47
55
  infiniteScroll = 'infiniteScroll',
48
56
  pagination = 'pagination'
49
57
  }
58
+
59
+ export type UNPayeeOnLoadCounterparty = {
60
+ id: string
61
+ attributes: {
62
+ name: string
63
+ bank?: string
64
+ routingNumber: string
65
+ accountNumber: string
66
+ accountType: UNCounterpartyAccountType
67
+ type: UNCounterpartyType
68
+ permissions: UNCounterpartyPermission
69
+ createdAt: Date
70
+ tags: {[key: string]: string}
71
+ }
72
+ relationships: {
73
+ customer: {
74
+ data: {
75
+ type: 'customer'
76
+ id: number
77
+ }
78
+ }
79
+ }
80
+ }
@@ -4,7 +4,7 @@ import { UNSecuritySettings, UNSnapshotProtectionStrategy } from '../types/share
4
4
  const WEB_SDK_RECOMMENDED_STRATEGY: UNWebVersioningStrategy = {
5
5
  type: UNVersioningStrategyType.upToNextMinor,
6
6
  major: 1,
7
- minor: 8,
7
+ minor: 10,
8
8
  };
9
9
 
10
10
  const DEFAULT_SECURITY_SETTINGS: UNSecuritySettings = {
@@ -1,4 +1,4 @@
1
- import { NativeModules } from 'react-native';
1
+ import { NativeModules, Platform } from 'react-native';
2
2
  import { fetchUnitScript } from './UnitSdk.api';
3
3
  import { UnitUiManager } from './unitUiManager/unitUiManager';
4
4
  import type { UNFonts } from '../types/shared/fonts.types';
@@ -26,7 +26,7 @@ export class UnitSDK {
26
26
  protected static fonts?: UNFonts;
27
27
  protected static signedNonce?: string;
28
28
  protected static pushProvisionModule?: typeof NativeModules;
29
- protected static sdkVersion = '1.14.0';
29
+ protected static sdkVersion = '1.15.0';
30
30
 
31
31
  public static init = async (
32
32
  env: UNEnvironment,
@@ -52,7 +52,9 @@ export class UnitSDK {
52
52
  store.dispatch(setLanguage(language));
53
53
  warnClientIfNeeded(this.webVersioningStrategy);
54
54
  const shouldProtectFromSnapshot = securitySettings.snapshotProtectionStrategy != UNSnapshotProtectionStrategy.None;
55
- UNSnapshotProtectionHelper.setIosSecurity(shouldProtectFromSnapshot, 'light');
55
+ if (Platform.OS === 'ios') {
56
+ UNSnapshotProtectionHelper.setIosSecurity(shouldProtectFromSnapshot, 'light');
57
+ }
56
58
  await fetchUnitScript();
57
59
  } catch (e) {
58
60
  console.log(e);
@@ -63,7 +65,7 @@ export class UnitSDK {
63
65
  return this.env != undefined;
64
66
  };
65
67
 
66
- public static setPushProvisioningModule = (pushProvisionModule: typeof NativeModules) => {
68
+ public static setPushProvisioningModule = (pushProvisionModule?: typeof NativeModules) => {
67
69
  this.pushProvisionModule = pushProvisionModule;
68
70
  };
69
71
 
@@ -9,13 +9,14 @@ import {
9
9
  UnitMessage,
10
10
  RequestDownloadEvent,
11
11
  RequestOpenLinkEvent,
12
+ MultiFactorAuthenticationFinishedEvent,
12
13
  } from '../messages/webMessages/unitMessages';
13
14
  import { getHtmlBody } from '../scripts/html/bodyHtml';
14
15
  import { fetchUnitScript } from '../unitSdkManager/UnitSdk.api';
15
16
  import { UnitSDK } from '../unitSdkManager/UnitSdkManager';
16
17
  import type { WebViewMessage } from '../messages/webMessages';
17
18
 
18
- import { getInfoParams, handleRequestDownload } from './WebComponent.utils';
19
+ import { getInfoParams, handleRequestDownload, injectEventToContinue } from './WebComponent.utils';
19
20
  import type { PresentationMode, WebComponentType } from '../types/internal/webComponent.types';
20
21
  import { getFontFacesString } from '../scripts/html/fontFaces';
21
22
  import type { RootState } from '../store';
@@ -116,10 +117,15 @@ export const WebComponent = React.forwardRef<WebView, WebComponentProps>(functio
116
117
  }, [props.params, unitScript, props.presentationMode, props.script, props.windowParams, globalTheme, globalLanguage, infoParams]);
117
118
 
118
119
  // Listen and update the live webComponents
119
- const updateVerifiedCustomerToken = (data: string) => {
120
- setItemInWindowUnitStore(webRef.current, UserDataKeys.unitVerifiedToken, data);
120
+ const handleMultiFactorAuthFinished = (data: MultiFactorAuthenticationFinishedEvent) => {
121
+ setItemInWindowUnitStore(webRef.current, UserDataKeys.unitVerifiedToken, data.unitVerifiedCustomerTokenString);
122
+ injectEventToContinue(webRef.current, {
123
+ parentInstanceId: data.parentInstanceId,
124
+ eventToContinue: data.eventToContinue
125
+ });
121
126
  };
122
- useListenerToEvent({ busEventKey: UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED, action: updateVerifiedCustomerToken });
127
+
128
+ useListenerToEvent({ busEventKey: UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED, action: handleMultiFactorAuthFinished });
123
129
 
124
130
  const onMessage = (e: WebViewMessageEvent) => {
125
131
  const message = JSON.parse(e.nativeEvent.data) as WebViewMessage;
@@ -145,14 +151,15 @@ export const WebComponent = React.forwardRef<WebView, WebComponentProps>(functio
145
151
  break;
146
152
  case UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED:
147
153
  if (message.details) {
148
- const data = message.details as string;
149
- UNStoreManagerHelper.saveValue(UserDataKeys.unitVerifiedToken, data);
154
+ const data = message.details as MultiFactorAuthenticationFinishedEvent;
155
+ UNStoreManagerHelper.saveValue(UserDataKeys.unitVerifiedToken, data.unitVerifiedCustomerTokenString);
150
156
  // update existing components - namely, the other webComponents will update their window as well as this webComponent
151
157
  dispatch(setEvent({
152
158
  key: UnitMessage.UNIT_MULTI_FACTOR_AUTH_FINISHED,
153
159
  data,
154
160
  }));
155
161
  }
162
+ props.onMessage && props.onMessage(message);
156
163
  break;
157
164
  case UnitMessage.UNIT_UNAUTHORIZED_TOKEN:
158
165
  UnitSDK.cleanUserData();
@@ -191,6 +198,7 @@ export const WebComponent = React.forwardRef<WebView, WebComponentProps>(functio
191
198
  onMessage={onMessage}
192
199
  androidLayerType='hardware'
193
200
  webviewDebuggingEnabled={__DEV__}
201
+ mediaCapturePermissionGrantType='grant'
194
202
  />
195
203
  );
196
204
  });
@@ -1,8 +1,9 @@
1
1
  import axios from 'axios';
2
2
  import { Share, NativeModules, Platform } from 'react-native';
3
3
  import * as AppInfo from '../utils/AppInfo';
4
- import type { RequestDownloadEvent } from '../messages/webMessages/unitMessages';
4
+ import type { EventToContinueEvent, RequestDownloadEvent } from '../messages/webMessages/unitMessages';
5
5
  import { UnitSDK } from '../unitSdkManager/UnitSdkManager';
6
+ import WebView from 'react-native-webview';
6
7
  const { RNShareFile } = NativeModules;
7
8
 
8
9
  export const getInfoParams = async () => {
@@ -41,3 +42,7 @@ export const handleRequestDownload = async (details: RequestDownloadEvent, onRea
41
42
  }
42
43
  }
43
44
  };
45
+
46
+ export const injectEventToContinue = (currentWeb: WebView | null, eventToContinueEvent: EventToContinueEvent) => {
47
+ currentWeb?.injectJavaScript(`dispatchEventToContinue('${JSON.stringify(eventToContinueEvent)}')`);
48
+ };
@@ -10,7 +10,8 @@ import {
10
10
  DISPATCH_ACTIVITY_FILTER_CHANGED_EVENT,
11
11
  DISPATCH_REQUEST_SHOW_SENSITIVE_DATA,
12
12
  DISPATCH_REQUEST_HIDE_SENSITIVE_DATA,
13
- SET_ITEM_IN_WINDOW_UNIT_STORE
13
+ SET_ITEM_IN_WINDOW_UNIT_STORE,
14
+ DISPATCH_EVENT_TO_CONTINUE
14
15
  } from '../scripts/html/bodyScript';
15
16
 
16
17
  export const HTML_PLACEHOLDER = {
@@ -88,6 +89,8 @@ const htmlText = `
88
89
 
89
90
  ${DISPATCH_RENDERING_EVENT}
90
91
 
92
+ ${DISPATCH_EVENT_TO_CONTINUE}
93
+
91
94
  ${DISPATCH_OPEN_ACTIONS_MENU}
92
95
 
93
96
  ${DISPATCH_REQUEST_HIDE_SENSITIVE_DATA}