Merge remote-tracking branch 'origin/PCP-4712-appswitch-qa' into PCP-4992-cross-browser-appswitch
Some checks failed
CI / PHP 7.4 (push) Has been cancelled
CI / PHP 8.0 (push) Has been cancelled
CI / PHP 8.1 (push) Has been cancelled
CI / PHP 8.2 (push) Has been cancelled
CI / PHP 8.3 (push) Has been cancelled
CI / PHP 8.4 (push) Has been cancelled
PR Playground Demo / prepare_version (push) Has been cancelled
PR Playground Demo / build_plugin (push) Has been cancelled
PR Playground Demo / create_archive (push) Has been cancelled
PR Playground Demo / Comment on PR with Playground details (push) Has been cancelled

This commit is contained in:
Alex P. 2025-08-25 08:28:12 +03:00
commit fe59ab01fb
No known key found for this signature in database
GPG key ID: 68E4DCB139B18520
5 changed files with 53 additions and 5 deletions

View file

@ -21,6 +21,7 @@ import {
onApproveSavePayment,
} from '../paypal-config';
import { useRef } from 'react';
import Spinner from '../../../../ppcp-button/resources/js/modules/Helper/Spinner';
const PAYPAL_GATEWAY_ID = 'ppcp-gateway';
@ -52,8 +53,11 @@ export const PayPalComponent = ( {
useState( false );
const [ paypalScriptLoaded, setPaypalScriptLoaded ] = useState( false );
const [ isFullPageSpinnerActive, setIsFullPageSpinnerActive ] =
useState( false );
const paypalButtonRef = useRef( null );
const spinnerRef = useRef( null );
if ( ! paypalScriptLoaded ) {
if ( ! paypalScriptPromise ) {
@ -70,6 +74,18 @@ export const PayPalComponent = ( {
? `${ config.id }-${ fundingSource }`
: config.id;
// Full-page spinner used to block UI interactions during flows like AppSwitch.
useEffect( () => {
if ( isFullPageSpinnerActive ) {
if ( ! spinnerRef.current ) {
spinnerRef.current = Spinner.fullPage();
}
spinnerRef.current.block();
} else if ( spinnerRef.current ) {
spinnerRef.current.unblock();
}
}, [ isFullPageSpinnerActive ] );
useEffect( () => {
// fill the form if in continuation (for product or mini-cart buttons)
if ( continuationFilled || ! config.scriptData.continuation?.order ) {
@ -286,6 +302,14 @@ export const PayPalComponent = ( {
};
}, [ onPaymentSetup, paypalOrder, activePaymentMethod ] );
useEffect( () => {
const unsubscribe = onCheckoutFail( () => {
setIsFullPageSpinnerActive( false );
} );
return unsubscribe;
}, [ onCheckoutFail ] );
useEffect( () => {
if ( activePaymentMethod !== methodId ) {
return;
@ -336,7 +360,8 @@ export const PayPalComponent = ( {
setGotoContinuationOnError,
onSubmit,
onError,
onClose
onClose,
setIsFullPageSpinnerActive
);
},
}
@ -491,7 +516,8 @@ export const PayPalComponent = ( {
setGotoContinuationOnError,
onSubmit,
onError,
onClose
onClose,
setIsFullPageSpinnerActive
)
}
onShippingOptionsChange={ getOnShippingOptionsChange(

View file

@ -64,8 +64,11 @@ export const handleApprove = async (
setGotoContinuationOnError,
onSubmit,
onError,
onClose
onClose,
setIsFullPageSpinnerActive
) => {
setIsFullPageSpinnerActive( true );
try {
let order;
@ -168,6 +171,8 @@ export const handleApprove = async (
} catch ( err ) {
console.error( err );
setIsFullPageSpinnerActive( false );
onError( err.message );
onClose();

View file

@ -8,6 +8,7 @@ import SimulateCart from '../Helper/SimulateCart';
import { strRemoveWord, strAddWord, throttle } from '../Helper/Utils';
import merge from 'deepmerge';
import { debounce } from '../../../../../ppcp-blocks/resources/js/Helper/debounce';
import ResumeFlowHelper from '../Helper/ResumeFlowHelper';
class SingleProductBootstrap {
constructor( gateway, renderer, errorHandler ) {
@ -53,7 +54,10 @@ class SingleProductBootstrap {
return;
}
this.render();
// Avoid re-rendering during the resume flow to prevent duplicate onApprove callbacks.
if ( ! ResumeFlowHelper.isResumeFlow() ) {
this.render();
}
this.renderer.enableSmartButtons( this.gateway.button.wrapper );
show( this.gateway.button.wrapper );

View file

@ -14,12 +14,16 @@ class Spinner {
background: '#fff',
opacity: 0.6,
},
baseZ: 10000,
} );
}
unblock() {
jQuery( this.target ).unblock();
}
}
static fullPage() {
return new Spinner( window );
}
}
export default Spinner;

View file

@ -1,3 +1,5 @@
import Spinner from '../Helper/Spinner';
const initiateRedirect = ( successUrl ) => {
/**
* Notice how this step initiates a redirect to a new page using a plain
@ -15,6 +17,10 @@ const initiateRedirect = ( successUrl ) => {
const onApprove = ( context, errorHandler ) => {
return ( data, actions ) => {
// Block the entire page during approval process
const spinner = Spinner.fullPage();
spinner.block();
const canCreateOrder =
! context.config.vaultingEnabled || data.paymentSource !== 'venmo';
@ -50,6 +56,9 @@ const onApprove = ( context, errorHandler ) => {
const orderReceivedUrl = approveData.data?.order_received_url;
initiateRedirect( orderReceivedUrl || context.config.redirect );
} )
.finally( () => {
spinner.unblock();
} );
};
};