1
- import { useEffect , useCallback , useRef } from "react" ;
2
1
import * as braze from "@braze/web-sdk" ;
3
2
import { ClassicCard } from "@braze/web-sdk" ;
3
+ import { generateAnonymousId } from "@ledgerhq/live-common/braze/anonymousUsers" ;
4
+ import { getEnv } from "@ledgerhq/live-env" ;
5
+ import { useCallback , useEffect , useRef } from "react" ;
6
+ import { useDispatch , useSelector } from "react-redux" ;
4
7
import { getBrazeConfig } from "~/braze-setup" ;
8
+ import getUser from "~/helpers/user" ;
5
9
import {
10
+ ActionContentCard ,
6
11
ContentCard as LedgerContentCard ,
7
12
LocationContentCard ,
8
- PortfolioContentCard ,
9
13
NotificationContentCard ,
10
14
Platform ,
11
- ActionContentCard ,
15
+ PortfolioContentCard ,
12
16
} from "~/types/dynamicContent" ;
13
- import { useDispatch , useSelector } from "react-redux" ;
14
17
import {
15
18
setActionCards ,
16
19
setDesktopCards ,
17
20
setNotificationsCards ,
18
21
setPortfolioCards ,
19
22
} from "../actions/dynamicContent" ;
20
- import getUser from "~/helpers/user" ;
21
- import {
22
- developerModeSelector ,
23
- trackingEnabledSelector ,
24
- dismissedContentCardsSelector ,
25
- anonymousBrazeIdSelector ,
26
- anonymousUserNotificationsSelector ,
27
- } from "../reducers/settings" ;
28
23
import {
29
24
clearDismissedContentCards ,
25
+ purgeExpiredAnonymousUserNotifications ,
30
26
setAnonymousBrazeId ,
31
- updateAnonymousUserNotifications ,
32
27
} from "../actions/settings" ;
33
- import { getEnv } from "@ledgerhq/live-env" ;
34
- import { getOldCampaignIds , generateAnonymousId } from "@ledgerhq/live-common/braze/anonymousUsers" ;
28
+ import {
29
+ anonymousBrazeIdSelector ,
30
+ developerModeSelector ,
31
+ dismissedContentCardsSelector ,
32
+ trackingEnabledSelector ,
33
+ } from "../reducers/settings" ;
35
34
36
35
const getDesktopCards = ( elem : braze . ContentCards ) =>
37
36
elem . cards . filter ( card => card . extras ?. platform === Platform . Desktop ) ;
@@ -53,92 +52,66 @@ export const compareCards = (a: LedgerContentCard, b: LedgerContentCard) => {
53
52
} ;
54
53
55
54
export const mapAsActionContentCard = ( card : ClassicCard ) : ActionContentCard => ( {
56
- id : String ( card . id ) ,
57
- title : card . extras ?. title ,
55
+ created : card . created ,
58
56
description : card . extras ?. description ,
59
- location : LocationContentCard . Action ,
57
+ id : String ( card . id ) ,
60
58
image : card . extras ?. image ,
61
59
link : card . extras ?. link ,
62
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63
- created : card . created as Date ,
60
+ location : LocationContentCard . Action ,
64
61
mainCta : card . extras ?. mainCta ,
65
- secondaryCta : card . extras ?. secondaryCta ,
66
62
order : parseInt ( card . extras ?. order ) ? parseInt ( card . extras ?. order ) : undefined ,
63
+ secondaryCta : card . extras ?. secondaryCta ,
64
+ title : card . extras ?. title ,
67
65
} ) ;
68
66
69
67
export const mapAsPortfolioContentCard = ( card : ClassicCard ) : PortfolioContentCard => ( {
70
- id : String ( card . id ) ,
71
- title : card . extras ?. title ,
72
- description : card . extras ?. description ,
68
+ created : card . created ,
73
69
cta : card . extras ?. cta ,
74
- tag : card . extras ?. tag ,
75
- location : LocationContentCard . Portfolio ,
70
+ description : card . extras ?. description ,
71
+ id : String ( card . id ) ,
76
72
image : card . extras ?. image ,
77
- url : card . extras ?. url ,
78
- path : card . extras ?. path ,
79
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
80
- created : card . created as Date ,
73
+ location : LocationContentCard . Portfolio ,
81
74
order : parseInt ( card . extras ?. order ) ? parseInt ( card . extras ?. order ) : undefined ,
75
+ path : card . extras ?. path ,
76
+ tag : card . extras ?. tag ,
77
+ title : card . extras ?. title ,
78
+ url : card . extras ?. url ,
82
79
} ) ;
83
80
84
81
export const mapAsNotificationContentCard = ( card : ClassicCard ) : NotificationContentCard => ( {
85
- id : String ( card . id ) ,
86
- title : card . extras ?. title ,
82
+ created : card . created ,
83
+ cta : card . extras ?. cta ,
87
84
description : card . extras ?. description ,
85
+ id : String ( card . id ) ,
88
86
location : LocationContentCard . NotificationCenter ,
89
- url : card . extras ?. url ,
87
+ order : parseInt ( card . extras ?. order ) ? parseInt ( card . extras ?. order ) : undefined ,
90
88
path : card . extras ?. path ,
91
- cta : card . extras ?. cta ,
92
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
93
- created : card . created as Date ,
89
+ title : card . extras ?. title ,
90
+ url : card . extras ?. url ,
94
91
viewed : card . viewed ,
95
- order : parseInt ( card . extras ?. order ) ? parseInt ( card . extras ?. order ) : undefined ,
96
92
} ) ;
97
93
94
+ /**
95
+ * TODO put this effectful logic into a provider instead
96
+ */
98
97
export async function useBraze ( ) {
99
98
const dispatch = useDispatch ( ) ;
100
99
const devMode = useSelector ( developerModeSelector ) ;
101
100
const contentCardsDissmissed = useSelector ( dismissedContentCardsSelector ) ;
102
- const anonymousUserNotifications = useSelector ( anonymousUserNotificationsSelector ) ;
103
101
const isTrackedUser = useSelector ( trackingEnabledSelector ) ;
104
102
const anonymousBrazeId = useRef ( useSelector ( anonymousBrazeIdSelector ) ) ;
105
103
106
104
const initBraze = useCallback ( async ( ) => {
107
105
const user = await getUser ( ) ;
108
106
const brazeConfig = getBrazeConfig ( ) ;
109
107
const isPlaywright = ! ! getEnv ( "PLAYWRIGHT_RUN" ) ;
110
- dispatch ( clearDismissedContentCards ( getOldCampaignIds ( contentCardsDissmissed ) ) ) ;
111
108
112
109
if ( ! anonymousBrazeId . current ) {
113
110
anonymousBrazeId . current = generateAnonymousId ( ) ;
114
111
dispatch ( setAnonymousBrazeId ( anonymousBrazeId . current ) ) ;
115
112
}
116
113
117
- /**
118
- * If the user is opt-out from analytics, we need to purge expired notifications persisted in the store/offline storage
119
- */
120
- if ( ! isTrackedUser ) {
121
- const expiredAnonymousUserNotifications = getOldCampaignIds ( anonymousUserNotifications ) ;
122
- if ( expiredAnonymousUserNotifications . length ) {
123
- const validAnonymousUserNotificationsOnly = Object . keys ( anonymousUserNotifications ) . reduce (
124
- ( validNotifications : Record < string , number > , key : string ) => {
125
- if ( ! expiredAnonymousUserNotifications . includes ( key ) ) {
126
- validNotifications [ key ] = anonymousUserNotifications [ key ] ;
127
- }
128
- return validNotifications ;
129
- } ,
130
- { } ,
131
- ) ;
132
- dispatch (
133
- updateAnonymousUserNotifications ( {
134
- notifications : validAnonymousUserNotificationsOnly ,
135
- purgeState : true ,
136
- } ) ,
137
- ) ;
138
- }
139
- }
140
-
141
- braze . initialize ( brazeConfig . apiKey , {
114
+ const isInitialized = braze . initialize ( brazeConfig . apiKey , {
142
115
baseUrl : brazeConfig . endpoint ,
143
116
allowUserSuppliedJavascript : true ,
144
117
enableHtmlInAppMessages : true ,
@@ -147,6 +120,11 @@ export async function useBraze() {
147
120
appVersion : isTrackedUser ? __APP_VERSION__ : undefined ,
148
121
} ) ;
149
122
123
+ if ( ! isInitialized ) {
124
+ console . warn ( "Failed to initialize Braze SDK" ) ;
125
+ return ;
126
+ }
127
+
150
128
// If it's playwright, we don't want to fetch content cards
151
129
if ( isPlaywright ) {
152
130
return ;
@@ -189,16 +167,22 @@ export async function useBraze() {
189
167
190
168
braze . automaticallyShowInAppMessages ( ) ;
191
169
braze . openSession ( ) ;
192
- } , [
193
- dispatch ,
194
- devMode ,
195
- isTrackedUser ,
196
- contentCardsDissmissed ,
197
- anonymousBrazeId ,
198
- anonymousUserNotifications ,
199
- ] ) ;
170
+ } , [ dispatch , devMode , isTrackedUser , contentCardsDissmissed , anonymousBrazeId ] ) ;
200
171
201
172
useEffect ( ( ) => {
202
173
initBraze ( ) ;
203
174
} , [ initBraze ] ) ;
175
+
176
+ // TODO should there be an interval to periodically purge dismissed cards?
177
+ useEffect ( ( ) => {
178
+ dispatch ( clearDismissedContentCards ( { now : new Date ( ) } ) ) ;
179
+ } , [ dispatch ] ) ;
180
+
181
+ // TODO should there be an interval to periodically purge old notifications?
182
+ useEffect ( ( ) => {
183
+ // If the user is opt-out from analytics, we need to purge expired notifications persisted in the store/offline storage
184
+ if ( ! isTrackedUser ) {
185
+ dispatch ( purgeExpiredAnonymousUserNotifications ( { now : new Date ( ) } ) ) ;
186
+ }
187
+ } , [ dispatch , isTrackedUser ] ) ;
204
188
}
0 commit comments