Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | import { useMutation, useQuery } from '@tanstack/react-query';
import { useCallback, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { fetchDownloadStatus, initiateDownload } from '../data/api/download';
import { keys } from '../data/query-client';
import type { RestoreItems } from '../types/restore';
type DownloadState =
| { phase: 'idle' }
| { phase: 'submitting' }
| { phase: 'progress'; percent: number }
| { phase: 'success'; downloadUrl: string }
| { phase: 'error'; message: string };
type Result = {
state: DownloadState;
submit: ( items: RestoreItems ) => void;
reset: () => void;
};
const POLL_INTERVAL_MS = 1500;
/**
* Real `useDownload` driving the modernized Download screen via the
* `/jetpack/v4/backups/download/$rewindId` bridge.
*
* Submit kicks off the WPCOM `prepare-download` and stores the download
* id; a polled status query then advances the state machine
* idle → submitting → progress → success | error.
*
* @param rewindId - The backup's rewind id.
* @return state + submit + reset.
*/
export function useDownload( rewindId: string ): Result {
const [ downloadId, setDownloadId ] = useState< number | null >( null );
const [ errorMessage, setErrorMessage ] = useState< string | null >( null );
const {
mutate: mutateInitiate,
reset: resetMutation,
isPending: isInitiating,
} = useMutation( {
mutationFn: ( items: RestoreItems ) => initiateDownload( rewindId, items ),
onSuccess: result => {
setDownloadId( result.id );
setErrorMessage( null );
},
onError: ( err: Error ) => {
setErrorMessage( err.message );
},
} );
const effectiveDownloadId = downloadId ?? -1;
const statusQuery = useQuery( {
queryKey: keys.downloadStatus( rewindId, effectiveDownloadId ),
queryFn: () => fetchDownloadStatus( rewindId, effectiveDownloadId ),
enabled: downloadId !== null,
refetchInterval: query =>
query.state.data?.status === 'in-progress' ? POLL_INTERVAL_MS : false,
} );
const submit = useCallback(
( items: RestoreItems ) => mutateInitiate( items ),
[ mutateInitiate ]
);
const reset = useCallback( () => {
setDownloadId( null );
setErrorMessage( null );
resetMutation();
}, [ resetMutation ] );
let state: DownloadState = { phase: 'idle' };
if ( errorMessage ) {
state = { phase: 'error', message: errorMessage };
} else if ( isInitiating ) {
state = { phase: 'submitting' };
} else if ( statusQuery.data?.status === 'completed' && statusQuery.data.url ) {
state = { phase: 'success', downloadUrl: statusQuery.data.url };
} else if ( statusQuery.data?.status === 'failed' ) {
state = { phase: 'error', message: __( 'Download failed.', 'jetpack-backup-pkg' ) };
} else if ( downloadId !== null && statusQuery.data ) {
state = {
phase: 'progress',
percent: Math.round( ( statusQuery.data.progress ?? 0 ) * 100 ),
};
} else if ( downloadId !== null ) {
state = { phase: 'progress', percent: 0 };
}
return { state, submit, reset };
}
|