Skip to content

Commit

Permalink
Merge pull request #283 from Automattic/update/sketch-upload-to-media…
Browse files Browse the repository at this point in the history
…-gallery

Sketch: upload to media gallery
  • Loading branch information
retrofox authored Sep 5, 2022
2 parents 11a790a + 28a8483 commit 17d5b65
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 19 deletions.
4 changes: 2 additions & 2 deletions blocks/sketch/editor.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.wp-block-a8c-sketch {
&__brush-style-popover {
/**
* Take care of default width for popover content.
*/
* Take care of default width for popover content.
*/
.components-popover__content {
min-width: initial;
}
Expand Down
83 changes: 66 additions & 17 deletions blocks/sketch/src/controls.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
/**
* Internal dependencies
*/
import { ColorControlIcon, BrushSizeControlIcon, BrushSizeIcon } from './icons';
/**
* WordPress dependencies
*/
import {
BlockControls,
InspectorControls,
useSetting,
} from '@wordpress/block-editor';
import { BlockControls, InspectorControls, useSetting } from '@wordpress/block-editor';
import { useDispatch } from '@wordpress/data';
import {
ColorPalette,
ExternalLink,
Icon,
PanelBody,
TextareaControl,
ToolbarButton,
ToolbarDropdownMenu,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { trash } from '@wordpress/icons';
import { trash, upload } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';

/**
* Internal dependencies
*/
import uploadBlobToMediaLibrary from '../../../lib/upload-image';
import svgDomToBlob from '../../../lib/svg-dom-to-blob';
import { ColorControlIcon, BrushSizeControlIcon, BrushSizeIcon } from './icons';

const brushes = [
{
Expand All @@ -46,8 +46,19 @@ const Controls = ( {
isEmpty,
title,
setTitle,
blockRef,
attributes,
} ) => {
const colors = useSetting( 'color.palette' ) || [];
const { createErrorNotice, createInfoNotice } = useDispatch( noticesStore );
function getSVGNodeElement() {
if ( ! blockRef.current ) {
return;
}

return blockRef.current.querySelector( 'svg' );
}

return (
<>
<BlockControls group="block">
Expand All @@ -58,7 +69,7 @@ const Controls = ( {
isAlternate: true,
} }
icon={ <Icon icon={ BrushSizeControlIcon } /> }
label={ __( 'Brush', 'sketch' ) }
label={ __( 'Brush', 'a8c-sketch' ) }
controls={ brushes.map( ( control ) => ( {
...control,
isActive: control.value === preset,
Expand All @@ -75,7 +86,7 @@ const Controls = ( {
icon={
<Icon icon={ <ColorControlIcon color={ color } /> } />
}
label={ __( 'Color', 'sketch' ) }
label={ __( 'Color', 'a8c-sketch' ) }
>
{ () => (
<ColorPalette
Expand All @@ -90,20 +101,57 @@ const Controls = ( {
<ToolbarButton
icon={ trash }
onClick={ clear }
label={ __( 'Clear canvas', 'sketch' ) }
label={ __( 'Clear canvas', 'a8c-sketch' ) }
disabled={ isEmpty }
/>

</BlockControls>

<BlockControls group="other">
<ToolbarButton
icon={ upload }
disabled={ isEmpty }
onClick={ () => {
svgDomToBlob( getSVGNodeElement(), function( blob ) {
uploadBlobToMediaLibrary( blob, { description: attributes?.title }, function( err, image ) {
if ( err ) {
return createErrorNotice( err );
}

createInfoNotice(
sprintf(
__( 'Image created and added to the library', 'a8c-sketch' ),
image.id,
),
{
id: `uploaded-image-${ image.id }`,
type: 'snackbar',
isDismissible: false,
actions: [
{
url: `/wp-admin/upload.php?item=${ image.id }`, // @ToDo - Get the rute properly
label: __( 'View Image', 'a8c-sketch' ),
},
],
}
);
} );
} );
} }
label={ __( 'Upload', 'a8c-sketch' ) }
/>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Settings' ) }>
<PanelBody title={ __( 'a8c-sketch' ) }>
<TextareaControl
label={ __( 'Description' ) }
label={ __( 'a8c-sketch' ) }
value={ title }
onChange={ setTitle }
help={
<>
{ __(
"Add a short-text description so it's recognized as the accessible name for the sketch."
"Add a short-text description so it's recognized as the accessible name for the sketch.",
'a8c-sketch'
) }
</>
}
Expand All @@ -113,4 +161,5 @@ const Controls = ( {
</>
);
};

export default Controls;
2 changes: 2 additions & 0 deletions blocks/sketch/src/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ const Edit = ( { attributes, isSelected, setAttributes } ) => {
isEmpty={ ! strokes.length }
title={ title }
setTitle={ setTitle }
blockRef={ ref }
attributes={ attributes }
/>
<figure { ...blockProps }>
<ResizableBox
Expand Down
28 changes: 28 additions & 0 deletions lib/svg-dom-to-blob/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

export default function svgDomToBlob( svgNode, fn ) {
if ( ! svgNode ) {
return;
}

// Get SVG Blob.
const svgString = new XMLSerializer().serializeToString( svgNode );
const DOMURL = self.URL || self.webkitURL || self;
const svgBlob = new Blob( [ svgString ], { type: "image/svg+xml;charset=utf-8" } );

// Start to convert SVG string to base64.
const canvas = document.createElement( 'canvas' );
const ctx = canvas.getContext( "2d" );
ctx.canvas.width = svgNode.width.baseVal.value;
ctx.canvas.height = svgNode.height.baseVal.value;

// Create an image based on the SVG string.
const img = new Image();
const url = DOMURL.createObjectURL( svgBlob );
img.onload = function() {
// Draw the image on the canvas.
ctx.drawImage( img, 0, 0 );
DOMURL.revokeObjectURL( canvas.toDataURL( 'image/png' ) );
canvas.toBlob( fn );
};
img.src = url;
};
49 changes: 49 additions & 0 deletions lib/upload-image/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* WordPress dependencies
*/
import { store as blockEditorStore } from '@wordpress/block-editor';
import { select } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

export default function uploadBlobToMediaLibrary(
imageBlob,
{
title = __( 'Image generated via Sketch block', 'a8c-sketch' ),
caption = '',
description = '',
},
fn
) {
const { getSettings } = select( blockEditorStore );
const mediaUpload = getSettings().mediaUpload;

if ( ! imageBlob ) {
return fn( __( 'No valid image', 'a8c-sketch' ) );
}

const reader = new window.FileReader();
reader.readAsDataURL( imageBlob );
reader.onloadend = () => {
mediaUpload( {
additionalData: {
title,
caption,
description,
},
allowedTypes: [ 'image' ],
filesList: [ imageBlob ],
onFileChange: ( images ) => {
if ( ! images?.length ) {
return;
}

const image = images[ 0 ];
if ( ! image?.id ) {
return;
}
fn( null, image );
},
onError: fn,
} );
};
}

0 comments on commit 17d5b65

Please sign in to comment.