Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Block: Add support for embedding PDFs #30857

Merged
merged 12 commits into from
Apr 21, 2021
2 changes: 1 addition & 1 deletion lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ function gutenberg_reregister_core_block_types() {
'code',
'column',
'columns',
'file',
'gallery',
'group',
'heading',
Expand Down Expand Up @@ -53,6 +52,7 @@ function gutenberg_reregister_core_block_types() {
'calendar.php' => 'core/calendar',
'categories.php' => 'core/categories',
'cover.php' => 'core/cover',
'file.php' => 'core/file',
'latest-comments.php' => 'core/latest-comments',
'latest-posts.php' => 'core/latest-posts',
'legacy-widget.php' => 'core/legacy-widget',
Expand Down
7 changes: 7 additions & 0 deletions packages/block-library/src/file/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
"type": "string",
"source": "html",
"selector": "a[download]"
},
"displayPreview": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this option and I believe we should probably extend it to various file types. Like QuickView for Gutenberg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it looks like previews for different file types are being discussed 👍🏻

"type": "boolean"
},
"previewHeight": {
"type": "number",
"default": 600
}
},
"supports": {
Expand Down
79 changes: 78 additions & 1 deletion packages/block-library/src/file/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';
import {
__unstableGetAnimateClassName as getAnimateClassName,
withNotices,
ResizableBox,
ToolbarButton,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
Expand All @@ -33,6 +34,10 @@ import { store as noticesStore } from '@wordpress/notices';
* Internal dependencies
*/
import FileBlockInspector from './inspector';
import { browserSupportsPdfs } from './utils';

export const MIN_PREVIEW_HEIGHT = 200;
export const MAX_PREVIEW_HEIGHT = 2000;
ntsekouras marked this conversation as resolved.
Show resolved Hide resolved

function ClipboardToolbarButton( { text, disabled } ) {
const { createNotice } = useDispatch( noticesStore );
Expand All @@ -54,7 +59,13 @@ function ClipboardToolbarButton( { text, disabled } ) {
);
}

function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
function FileEdit( {
attributes,
isSelected,
setAttributes,
noticeUI,
noticeOperations,
} ) {
const {
id,
fileName,
Expand All @@ -63,6 +74,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
textLinkTarget,
showDownloadButton,
downloadButtonText,
displayPreview,
previewHeight,
} = attributes;
const [ hasError, setHasError ] = useState( false );
const { media, mediaUpload } = useSelect(
Expand All @@ -76,6 +89,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
[ id ]
);

const { toggleSelection } = useDispatch( blockEditorStore );

useEffect( () => {
// Upload a file drag-and-dropped into the editor
if ( isBlobURL( href ) ) {
Expand All @@ -101,11 +116,14 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
function onSelectFile( newMedia ) {
if ( newMedia && newMedia.url ) {
setHasError( false );
const isPdf = newMedia.url.endsWith( '.pdf' );
setAttributes( {
href: newMedia.url,
fileName: newMedia.title,
textLinkHref: newMedia.url,
id: newMedia.id,
displayPreview: isPdf ? true : undefined,
previewHeight: isPdf ? 600 : undefined,
} );
}
}
Expand Down Expand Up @@ -138,6 +156,25 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
} );
}

function changeDisplayPreview( newValue ) {
setAttributes( { displayPreview: newValue } );
}

function handleOnResizeStop( event, direction, elt, delta ) {
toggleSelection( true );

const newHeight = parseInt( previewHeight + delta.height, 10 );
setAttributes( { previewHeight: newHeight } );
}

function changePreviewHeight( newValue ) {
const newHeight = Math.max(
parseInt( newValue, 10 ),
MIN_PREVIEW_HEIGHT
);
setAttributes( { previewHeight: newHeight } );
}

const attachmentPage = media && media.link;

const blockProps = useBlockProps( {
Expand All @@ -149,6 +186,8 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
),
} );

const displayPreviewInEditor = browserSupportsPdfs() && displayPreview;

if ( ! href || hasError ) {
return (
<div { ...blockProps }>
Expand Down Expand Up @@ -179,6 +218,10 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
changeLinkDestinationOption,
changeOpenInNewWindow,
changeShowDownloadButton,
displayPreview,
changeDisplayPreview,
previewHeight,
changePreviewHeight,
} }
/>
<BlockControls group="other">
Expand All @@ -195,6 +238,40 @@ function FileEdit( { attributes, setAttributes, noticeUI, noticeOperations } ) {
/>
</BlockControls>
<div { ...blockProps }>
{ displayPreviewInEditor && (
<ResizableBox
size={ { height: previewHeight } }
pento marked this conversation as resolved.
Show resolved Hide resolved
minHeight={ MIN_PREVIEW_HEIGHT }
maxHeight={ MAX_PREVIEW_HEIGHT }
minWidth="100%"
grid={ [ 10, 10 ] }
enable={ {
top: false,
right: false,
bottom: true,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
} }
onResizeStart={ () => toggleSelection( false ) }
onResizeStop={ handleOnResizeStop }
showHandle={ isSelected }
>
<object
className="wp-block-file__preview"
data={ href }
type="application/pdf"
aria-label={ __(
'Embed of the selected PDF file.'
) }
/>
{ ! isSelected && (
<div className="wp-block-file__preview-overlay" />
) }
</ResizableBox>
) }
<div className={ 'wp-block-file__content-wrapper' }>
<RichText
style={ { display: 'inline-block' } }
Expand Down
25 changes: 25 additions & 0 deletions packages/block-library/src/file/editor.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
.wp-block-file {
.wp-block[data-align="left"] > &,
.wp-block[data-align="right"] > & {
// Stop file block from collapsing when floated.
height: auto;
}

display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
margin-bottom: 0;

.components-resizable-box__container {
margin-bottom: 1em;
}

.wp-block-file__preview {
margin-bottom: 1em;
width: 100%;
height: 100%;
}

.wp-block-file__preview-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

.wp-block-file__content-wrapper {
flex-grow: 1;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/block-library/src/file/frontend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Internal dependencies
*/
import { hidePdfEmbedsOnUnsupportedBrowsers } from './utils';

hidePdfEmbedsOnUnsupportedBrowsers();
38 changes: 38 additions & 0 deletions packages/block-library/src/file/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* Server-side rendering of the `core/file` block.
*
* @package WordPress
*/

/**
* When the `core/file` block is rendering, check if we need to enqueue the `'wp-block-library-file` script.
*
* @param array $attributes The block attributes.
* @param array $content The block content.
*
* @return string Returns the block content.
*/
function render_block_core_file( $attributes, $content ) {
if ( ! empty( $attributes['displayPreview'] ) ) {
pento marked this conversation as resolved.
Show resolved Hide resolved
// Check if it's already enqueued, so we don't add the inline script multiple times.
if ( ! wp_script_is( 'wp-block-library-file' ) ) {
wp_enqueue_script( 'wp-block-library-file', plugins_url( 'file/frontend.js', __FILE__ ) );
}
}

return $content;
}

/**
* Registers the `core/file` block on server.
*/
function register_block_core_file() {
register_block_type_from_metadata(
__DIR__ . '/file',
array(
'render_callback' => 'render_block_core_file',
)
);
}
add_action( 'init', 'register_block_core_file' );
42 changes: 41 additions & 1 deletion packages/block-library/src/file/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,30 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, SelectControl, ToggleControl } from '@wordpress/components';
import {
PanelBody,
RangeControl,
SelectControl,
ToggleControl,
} from '@wordpress/components';
import { InspectorControls } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { MIN_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT } from './edit';

export default function FileBlockInspector( {
hrefs,
openInNewWindow,
showDownloadButton,
changeLinkDestinationOption,
changeOpenInNewWindow,
changeShowDownloadButton,
displayPreview,
changeDisplayPreview,
previewHeight,
pento marked this conversation as resolved.
Show resolved Hide resolved
changePreviewHeight,
} ) {
const { href, textLinkHref, attachmentPage } = hrefs;

Expand All @@ -26,6 +40,32 @@ export default function FileBlockInspector( {
return (
<>
<InspectorControls>
{ href.endsWith( '.pdf' ) && (
<PanelBody title={ __( 'PDF settings' ) }>
<ToggleControl
label={ __( 'Show inline embed' ) }
help={
displayPreview
? __(
"Note: Most phone and tablet browsers won't display embedded PDFs."
)
: null
}
checked={ !! displayPreview }
onChange={ changeDisplayPreview }
/>
<RangeControl
label={ __( 'Height in pixels' ) }
min={ MIN_PREVIEW_HEIGHT }
max={ Math.max(
MAX_PREVIEW_HEIGHT,
previewHeight
) }
value={ previewHeight }
onChange={ changePreviewHeight }
/>
</PanelBody>
) }
<PanelBody title={ __( 'Text link settings' ) }>
<SelectControl
label={ __( 'Link to' ) }
Expand Down
29 changes: 28 additions & 1 deletion packages/block-library/src/file/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { RichText, useBlockProps } from '@wordpress/block-editor';
import { __, sprintf } from '@wordpress/i18n';

export default function save( { attributes } ) {
const {
Expand All @@ -11,16 +12,42 @@ export default function save( { attributes } ) {
textLinkTarget,
showDownloadButton,
downloadButtonText,
displayPreview,
previewHeight,
} = attributes;

const pdfEmbedLabel = RichText.isEmpty( fileName )
ntsekouras marked this conversation as resolved.
Show resolved Hide resolved
? __( 'PDF embed' )
: sprintf(
/* translators: %s: filename. */
__( 'Embed of %s.' ),
fileName
);

return (
href && (
<div { ...useBlockProps.save() }>
{ displayPreview && (
<>
<object
className="wp-block-file__embed"
data={ href }
type="application/pdf"
style={ {
width: '100%',
height: `${ previewHeight }px`,
pento marked this conversation as resolved.
Show resolved Hide resolved
} }
aria-label={ pdfEmbedLabel }
/>
</>
) }
{ ! RichText.isEmpty( fileName ) && (
<a
href={ textLinkHref }
target={ textLinkTarget }
rel={ textLinkTarget ? 'noreferrer noopener' : false }
rel={
textLinkTarget ? 'noreferrer noopener' : undefined
}
>
<RichText.Content value={ fileName } />
</a>
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/file/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
text-align: right;
}

.wp-block-file__embed {
margin-bottom: 1em;
}

.wp-block-file__button {
background: #32373c;
border-radius: 2em;
Expand Down
Loading