Skip to content

Commit e659c64

Browse files
committed
support visibility change for manual app switch flow
1 parent 01a491d commit e659c64

File tree

3 files changed

+79
-21
lines changed

3 files changed

+79
-21
lines changed

src/ui/buttons/props.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,10 @@ export type ButtonProps = {|
510510
// change any to HashChangeEvent when we move to typescript
511511
// eslint-disable-next-line flowtype/no-weak-types
512512
hashChangeHandler: (event: any) => void,
513+
listenForVisibilityChange: () => void,
514+
removeListenerForVisibilityChanges: () => void,
515+
// Not passed to child iframe
516+
visibilityChangeHandler: () => void,
513517

514518
fundingSource?: ?$Values<typeof FUNDING>,
515519
intent: $Values<typeof INTENT>,

src/zoid/buttons/component.jsx

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ import {
5050
} from "@paypal/funding-components/src";
5151
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
5252
import { create, EVENT, type ZoidComponent } from "@krakenjs/zoid/src";
53-
import { send as postRobotSend } from "@krakenjs/post-robot/src";
5453
import {
5554
uniqueID,
5655
memoize,
@@ -98,6 +97,7 @@ import {
9897
getButtonSize,
9998
getButtonExperiments,
10099
getModal,
100+
sendPostRobotMessageToButtonIframe,
101101
} from "./util";
102102

103103
export type ButtonsComponent = ZoidComponent<
@@ -305,27 +305,13 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
305305
type: "function",
306306
sendToChild: false,
307307
queryParam: false,
308-
required: false,
309308
value: () => (event) => {
310-
const iframes = document.querySelectorAll("iframe");
311-
312-
// I don't understand why but trying to make iframes which is a NodeList
313-
// into an Iterable (so we could do a for..of loop or .forEach) is not
314-
// working. It ends up iterating over itself so instead of looping over the contents
315-
// of the NodeList you loop over the NodeList itself which is extremely unexpected
316-
// for..in works though :shrug: - Shane 11 Dec 2024
317-
for (let i = 0; i < iframes.length; i++) {
318-
if (iframes[i].name.includes("zoid__paypal_buttons")) {
319-
postRobotSend(
320-
iframes[i].contentWindow,
321-
"paypal-hashchange",
322-
{
323-
url: event.newURL,
324-
},
325-
{ domain: getPayPalDomain() }
326-
);
327-
}
328-
}
309+
sendPostRobotMessageToButtonIframe({
310+
eventName: "paypal-hashchange",
311+
payload: {
312+
url: event.newURL,
313+
},
314+
});
329315
},
330316
},
331317

@@ -349,6 +335,48 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
349335
},
350336
},
351337

338+
visibilityChangeHandler: {
339+
type: "function",
340+
sendToChild: false,
341+
queryParam: false,
342+
value: () => () => {
343+
sendPostRobotMessageToButtonIframe({
344+
eventName: "paypal-visibilitychange",
345+
payload: {
346+
url: window.location.href,
347+
// eslint-disable-next-line compat/compat
348+
visibilityState: document.visibilityState,
349+
},
350+
});
351+
},
352+
},
353+
354+
listenForVisibilityChange: {
355+
type: "function",
356+
queryParam: false,
357+
value:
358+
({ props }) =>
359+
() => {
360+
window.addEventListener(
361+
"visibilitychange",
362+
props.hashChangeHandler
363+
);
364+
},
365+
},
366+
367+
removeListenerForVisibilityChanges: {
368+
type: "function",
369+
queryParam: false,
370+
value:
371+
({ props }) =>
372+
() => {
373+
window.removeEventListener(
374+
"visibilitychange",
375+
props.hashChangeHandler
376+
);
377+
},
378+
},
379+
352380
// allowBillingPayments prop is used by Honey Extension to render the one-click button
353381
// with payment methods & to use the payment methods instead of the Billing Agreement
354382
allowBillingPayments: {

src/zoid/buttons/util.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
once,
1515
memoize,
1616
} from "@krakenjs/belter/src";
17+
import { send as postRobotSend } from "@krakenjs/post-robot/src";
1718
import {
1819
getEnableFunding,
1920
getLogger,
@@ -23,6 +24,7 @@ import {
2324
getComponents,
2425
getEnv,
2526
getNamespace,
27+
getPayPalDomain,
2628
getFirstRenderExperiments,
2729
} from "@paypal/sdk-client/src";
2830
import { FUNDING, FPTI_KEY } from "@paypal/sdk-constants/src";
@@ -424,3 +426,27 @@ export const getModal: (
424426
});
425427
}
426428
});
429+
430+
export const sendPostRobotMessageToButtonIframe = ({
431+
eventName,
432+
payload,
433+
}: // eslint-disable-next-line flowtype/require-exact-type
434+
{
435+
eventName: string,
436+
payload: Object,
437+
}) => {
438+
const iframes = document.querySelectorAll("iframe");
439+
440+
// I don't understand why but trying to make iframes which is a NodeList
441+
// into an Iterable (so we could do a for..of loop or .forEach) is not
442+
// working. It ends up iterating over itself so instead of looping over the contents
443+
// of the NodeList you loop over the NodeList itself which is extremely unexpected
444+
// for..in works though :shrug: - Shane 11 Dec 2024
445+
for (let i = 0; i < iframes.length; i++) {
446+
if (iframes[i].name.includes("zoid__paypal_buttons")) {
447+
postRobotSend(iframes[i].contentWindow, eventName, payload, {
448+
domain: getPayPalDomain(),
449+
});
450+
}
451+
}
452+
};

0 commit comments

Comments
 (0)