PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.7.2
GenerateBlocks v1.7.2
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / blocks / image / edit.js
generateblocks / src / blocks / image Last commit date
components 3 years ago css 3 years ago block.json 4 years ago edit.js 3 years ago editor.scss 3 years ago index.js 3 years ago save.js 4 years ago transforms.js 4 years ago
edit.js
203 lines
1 import './editor.scss';
2 import ImageContentRenderer from './components/ImageContentRenderer';
3 import { compose } from '@wordpress/compose';
4 import withDynamicContent from '../../extend/dynamic-content/hoc/withDynamicContent';
5 import { withDeviceType, withUniqueId } from '../../hoc';
6 import ComponentCSS from './components/ComponentCSS';
7 import { useDispatch, useSelect } from '@wordpress/data';
8 import { useEffect, useState } from '@wordpress/element';
9 import { store as noticesStore } from '@wordpress/notices';
10 import ImageSettingsControls from './components/inspector-controls/ImageSettingsControl';
11 import { InspectorAdvancedControls, store as blockEditorStore } from '@wordpress/block-editor';
12 import { useEntityProp } from '@wordpress/core-data';
13 import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';
14 import HTMLAnchor from '../../components/html-anchor';
15 import { pick } from 'lodash';
16 import { withBlockContext } from '../../block-context';
17 import GenerateBlocksInspectorControls from '../../extend/inspector-control';
18 import { applyFilters } from '@wordpress/hooks';
19 import getDeviceType from '../../utils/get-device-type';
20
21 function ImageEdit( props ) {
22 const {
23 attributes,
24 setAttributes,
25 context,
26 ContentRenderer = ImageContentRenderer,
27 } = props;
28
29 const {
30 useDynamicData,
31 dynamicContentType,
32 sizeSlug,
33 mediaId,
34 mediaUrl,
35 anchor,
36 } = attributes;
37
38 const deviceType = getDeviceType();
39 const { createErrorNotice } = useDispatch( noticesStore );
40 const [ temporaryURL, setTemporaryURL ] = useState();
41 const postType = 'post-type' === attributes.dynamicSource ? attributes.postType : context.postType;
42 const postId = 'post-type' === attributes.dynamicSource ? attributes.postId : context.postId;
43 const [ featuredImage ] = useEntityProp( 'postType', postType, 'featured_media', postId );
44 const isTemporaryImage = ( id, url ) => ! id && isBlobURL( url );
45
46 const { mediaUpload } = useSelect( ( select ) => {
47 const { getSettings } = select( blockEditorStore );
48 return pick( getSettings(), [ 'imageDefaultSize', 'mediaUpload' ] );
49 }, [] );
50
51 const onSelectImage = ( image ) => {
52 if ( ! image || ! image.url ) {
53 setAttributes( {
54 mediaUrl: undefined,
55 mediaId: undefined,
56 title: undefined,
57 alt: undefined,
58 } );
59
60 return;
61 }
62
63 if ( isBlobURL( image.url ) ) {
64 setTemporaryURL( image.url );
65 return;
66 }
67
68 setTemporaryURL();
69
70 if (
71 !! image &&
72 (
73 ! useDynamicData ||
74 (
75 !! useDynamicData &&
76 ! dynamicContentType
77 )
78 )
79 ) {
80 const imageUrl = ( image?.sizes && image?.sizes[ sizeSlug ]?.url ) || image?.url;
81
82 setAttributes( {
83 mediaId: image?.id,
84 mediaUrl: imageUrl,
85 alt: image?.alt,
86 title: image?.title,
87 } );
88 }
89 };
90
91 const onSelectURL = ( newURL ) => {
92 if ( newURL !== mediaUrl ) {
93 setAttributes( {
94 mediaUrl: newURL,
95 mediaId: undefined,
96 title: '',
97 alt: '',
98 } );
99 }
100 };
101
102 const onUploadError = ( message ) => {
103 createErrorNotice( message[ 2 ], { type: 'snackbar' } );
104 };
105
106 const onResetImage = () => {
107 setAttributes( {
108 mediaId: undefined,
109 mediaUrl: '',
110 alt: '',
111 title: '',
112 width: '',
113 widthTablet: '',
114 widthMobile: '',
115 height: '',
116 heightTablet: '',
117 heightMobile: '',
118 } );
119 };
120
121 useEffect( () => {
122 if ( ! sizeSlug ) {
123 setAttributes( { sizeSlug: 'full' } );
124 }
125 }, [] );
126
127 let isTemp = isTemporaryImage( mediaId, mediaUrl );
128
129 // Upload a temporary image on mount.
130 useEffect( () => {
131 if ( ! isTemp ) {
132 return;
133 }
134
135 const file = getBlobByURL( mediaUrl );
136
137 if ( file ) {
138 mediaUpload( {
139 filesList: [ file ],
140 onFileChange: ( [ img ] ) => {
141 onSelectImage( img );
142 },
143 allowedTypes: [ 'image' ],
144 onError: ( message ) => {
145 isTemp = false;
146 onUploadError( message );
147 },
148 } );
149 }
150 }, [] );
151
152 // If an image is temporary, revoke the Blob url when it is uploaded (and is
153 // no longer temporary).
154 useEffect( () => {
155 if ( isTemp ) {
156 setTemporaryURL( mediaUrl );
157 return;
158 }
159 revokeBlobURL( temporaryURL );
160 }, [ isTemp, mediaUrl ] );
161
162 return (
163 <>
164 <GenerateBlocksInspectorControls
165 attributes={ attributes }
166 setAttributes={ setAttributes }
167 >
168 { applyFilters( 'generateblocks.editor.settingsPanel', undefined, { ...props, device: deviceType } ) }
169
170 <ImageSettingsControls
171 attributes={ attributes }
172 setAttributes={ setAttributes }
173 deviceType={ deviceType }
174 />
175 </GenerateBlocksInspectorControls>
176
177 <InspectorAdvancedControls>
178 <HTMLAnchor { ...props } anchor={ anchor } />
179 </InspectorAdvancedControls>
180
181 <ComponentCSS { ...props } deviceType={ deviceType } />
182
183 <ContentRenderer
184 { ...props }
185 temporaryURL={ temporaryURL }
186 featuredImage={ featuredImage }
187 onSelectImage={ onSelectImage }
188 onSelectURL={ onSelectURL }
189 onUploadError={ onUploadError }
190 onResetImage={ onResetImage }
191 deviceType={ deviceType }
192 />
193 </>
194 );
195 }
196
197 export default compose(
198 withDeviceType,
199 withBlockContext,
200 withDynamicContent,
201 withUniqueId,
202 )( ImageEdit );
203