@automattic/shopping-cart
Version:
A library to use the WordPress.com shopping cart.
94 lines (80 loc) • 2.99 kB
text/typescript
import debugFactory from 'debug';
import { useEffect, useContext } from 'react';
import { cartKeysThatDoNotAllowFetch } from './cart-keys';
import ShoppingCartOptionsContext from './shopping-cart-options-context';
import useManagerClient from './use-manager-client';
import type { CartKey } from './types';
const debug = debugFactory( 'shopping-cart:use-refetch-on-focus' );
// The number of seconds within that must have passed before we allow an
// automatic refetch on focus.
const minimumFetchInterval = 60;
function convertMsToSecs( ms: number ): number {
return Math.floor( ms / 1000 );
}
function isFocused(): boolean {
return [ undefined, 'visible', 'prerender' ].includes( document.visibilityState );
}
function isOffline(): boolean {
try {
return ! window.navigator.onLine;
} catch ( err ) {
debug( 'failed to check onLine status; ignoring check', err );
return false;
}
}
export default function useRefetchOnFocus( cartKey: CartKey | undefined ): void {
const managerClient = useManagerClient( 'useRefetchOnFocus' );
const manager = managerClient.forCartKey( cartKey );
const { refetchOnWindowFocus } = useContext( ShoppingCartOptionsContext );
useEffect( () => {
if ( ! refetchOnWindowFocus ) {
debug( 'refetchOnWindowFocus false; not listening' );
return;
}
if ( ! cartKey ) {
debug( 'cartKey falsy; not listening' );
return;
}
if ( cartKeysThatDoNotAllowFetch.includes( cartKey ) ) {
debug( 'cartKey not fetchable; not listening' );
return;
}
function wasLastFetchRecent(): boolean {
const nowInSeconds = convertMsToSecs( Date.now() );
const { responseCart: lastCart } = manager.getState();
const lastRefreshTime = lastCart.cart_generated_at_timestamp;
const secondsSinceLastFetch = nowInSeconds - lastRefreshTime;
debug( 'last fetch was', secondsSinceLastFetch, 'seconds ago' );
return secondsSinceLastFetch < minimumFetchInterval;
}
function handleFocusChange(): void {
if ( ! isFocused() ) {
debug( 'window was made invisible; ignoring' );
return;
}
if ( wasLastFetchRecent() ) {
debug( 'last fetch was quite recent; ignoring' );
return;
}
if ( isOffline() ) {
debug( 'network is offline; ignoring' );
return;
}
debug( 'window was refocused; refetching' );
manager.actions.reloadFromServer().catch( () => {
// No need to do anything here. Errors will be surfaced by the cart
// accessors manually.
} );
}
debug( 'adding focus listeners' );
window.addEventListener( 'visibilitychange', handleFocusChange );
window.addEventListener( 'focus', handleFocusChange );
window.addEventListener( 'online', handleFocusChange );
return () => {
debug( 'removing focus listeners' );
window.removeEventListener( 'visibilitychange', handleFocusChange );
window.removeEventListener( 'focus', handleFocusChange );
window.removeEventListener( 'online', handleFocusChange );
};
}, [ cartKey, refetchOnWindowFocus, manager ] );
}