/* global beyondwordsData, BeyondWords */ ( function () { 'use strict'; /** * Content statuses that mean "still processing" — keep polling. * * @type {string[]} */ const NON_TERMINAL_STATUSES = [ 'draft', 'queued', 'processing' ]; /** * Poll `fetchStatus` until the content reaches a terminal status. * * Mirror of src/editor/lib/poll-content-status.js, inlined because this * classic-editor script is enqueued raw (not built) and cannot `import`. * * @param {Object} options Options. * @param {Function} options.fetchStatus () => Promise<{ status }>. * @param {Function} [options.onTick] Called per non-terminal poll. * @param {Function} [options.isHidden] () => boolean; skip the call when true. * @param {Function} [options.isCancelled] () => boolean; stop polling when true. * @param {number} [options.intervalMs] Delay between polls. * @param {number} [options.timeoutMs] Overall time budget. * @return {Promise<{status: (string|undefined), timedOut: boolean}>} Result; * a superseded (cancelled) poll stops without resolving. */ function pollContentStatus( options ) { const fetchStatus = options.fetchStatus; const onTick = options.onTick; const isHidden = options.isHidden; const isCancelled = options.isCancelled || function () { return false; }; const intervalMs = options.intervalMs || 3000; const timeoutMs = options.timeoutMs || 120000; const start = Date.now(); let lastStatus; let hiddenMs = 0; return new Promise( function ( resolve ) { function tick() { if ( isCancelled() ) { return; } // Budget measures visible time — a hidden tab resumes polling on // return instead of timing out having never fetched. if ( Date.now() - start - hiddenMs >= timeoutMs ) { resolve( { status: lastStatus, timedOut: true } ); return; } // Skip the upstream call while the tab is hidden — each poll is // an uncached upstream API call. if ( isHidden && isHidden() ) { const hiddenAt = Date.now(); setTimeout( function () { hiddenMs += Date.now() - hiddenAt; tick(); }, intervalMs ); return; } fetchStatus() .then( function ( result ) { if ( isCancelled() ) { return; } const status = result && result.status; lastStatus = status; if ( NON_TERMINAL_STATUSES.indexOf( status ) === -1 ) { resolve( { status, timedOut: false } ); return; } if ( onTick ) { onTick( status ); } setTimeout( tick, intervalMs ); } ) .catch( function () { if ( isCancelled() ) { return; } // Transient failure — keep polling until the budget. setTimeout( tick, intervalMs ); } ); } tick(); } ); } /** * Resolve once the BeyondWords player SDK global is available. * * The SDK loads from a deferred