A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1import type { MediaUploadHandler } from '../media/mediaUpload';
2
3/** Read a file into a `data:` URL (base64) for inline preview. */
4function readAsDataUrl( file: File ): Promise< string > {
5 return new Promise( ( resolve, reject ) => {
6 const reader = new FileReader();
7 reader.onload = () => resolve( reader.result as string );
8 reader.onerror = () =>
9 reject( reader.error ?? new Error( `Could not read "${ file.name }".` ) );
10 reader.readAsDataURL( file );
11 } );
12}
13
14/**
15 * A Gutenberg `mediaUpload` handler for the writing-first flow (design 2026-06-17): it
16 * previews each file from a `data:` URL and uploads NOTHING to a PDS. The real upload is
17 * deferred to publish (see `upload-held.ts`), so the editor works while signed out.
18 *
19 * Like the eager handler it must preview from a `data:` URL, never a `blob:` URL — the Image
20 * block treats a `blob:` URL as still-uploading and re-runs its upload hook forever.
21 */
22export function createDeferredMediaUpload(): MediaUploadHandler {
23 return async function deferredMediaUpload( {
24 filesList,
25 onFileChange,
26 onError,
27 maxUploadFileSize,
28 } ): Promise< void > {
29 for ( const file of Array.from( filesList ) ) {
30 try {
31 if ( maxUploadFileSize && file.size > maxUploadFileSize ) {
32 const mb = Math.round( maxUploadFileSize / 1024 / 1024 );
33 throw new Error( `"${ file.name }" exceeds the ${ mb }MB limit.` );
34 }
35 const previewUrl = await readAsDataUrl( file );
36 // No `id`: PDS blobs aren't WP attachments (mirrors the eager handler).
37 onFileChange( [ { url: previewUrl, alt: '' } ] );
38 } catch ( error ) {
39 onError?.( error instanceof Error ? error : new Error( String( error ) ) );
40 }
41 }
42 };
43}