@wordpress/block-library
Version:
Block library for the WordPress editor.
551 lines (485 loc) • 16.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.FileEdit = void 0;
var _element = require("@wordpress/element");
var _reactNative = require("react-native");
var _clipboard = _interopRequireDefault(require("@react-native-clipboard/clipboard"));
var _reactNativeBridge = require("@wordpress/react-native-bridge");
var _blockEditor = require("@wordpress/block-editor");
var _components = require("@wordpress/components");
var _icons = require("@wordpress/icons");
var _i18n = require("@wordpress/i18n");
var _compose = require("@wordpress/compose");
var _data = require("@wordpress/data");
var _url = require("@wordpress/url");
var _coreData = require("@wordpress/core-data");
var _style = _interopRequireDefault(require("./style.scss"));
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const URL_COPIED_NOTIFICATION_DURATION_MS = 1500;
const MIN_WIDTH = 40;
class FileEdit extends _element.Component {
constructor(props) {
super(props);
this.state = {
isUploadInProgress: false,
isSidebarLinkSettings: false,
placeholderTextWidth: 0,
maxWidth: 0
};
this.timerRef = null;
this.onLayout = this.onLayout.bind(this);
this.onSelectFile = this.onSelectFile.bind(this);
this.onChangeFileName = this.onChangeFileName.bind(this);
this.onChangeDownloadButtonText = this.onChangeDownloadButtonText.bind(this);
this.updateMediaProgress = this.updateMediaProgress.bind(this);
this.finishMediaUploadWithSuccess = this.finishMediaUploadWithSuccess.bind(this);
this.finishMediaUploadWithFailure = this.finishMediaUploadWithFailure.bind(this);
this.getFileComponent = this.getFileComponent.bind(this);
this.onChangeDownloadButtonVisibility = this.onChangeDownloadButtonVisibility.bind(this);
this.onCopyURL = this.onCopyURL.bind(this);
this.onChangeOpenInNewWindow = this.onChangeOpenInNewWindow.bind(this);
this.onChangeLinkDestinationOption = this.onChangeLinkDestinationOption.bind(this);
this.onShowLinkSettings = this.onShowLinkSettings.bind(this);
this.onFilePressed = this.onFilePressed.bind(this);
this.mediaUploadStateReset = this.mediaUploadStateReset.bind(this);
}
componentDidMount() {
const {
attributes,
setAttributes
} = this.props;
const {
downloadButtonText
} = attributes;
if (downloadButtonText === undefined || downloadButtonText === '') {
setAttributes({
downloadButtonText: (0, _i18n._x)('Download', 'button label')
});
}
if (attributes.id && attributes.url && (0, _url.getProtocol)(attributes.url) === 'file:') {
(0, _reactNativeBridge.mediaUploadSync)();
}
}
componentWillUnmount() {
clearTimeout(this.timerRef);
}
componentDidUpdate(prevProps) {
if (prevProps.isSidebarOpened && !this.props.isSidebarOpened && this.state.isSidebarLinkSettings) {
this.setState({
isSidebarLinkSettings: false
});
}
}
onSelectFile(media) {
this.props.setAttributes({
href: media.url,
fileName: media.title,
textLinkHref: media.url,
id: media.id
});
}
onChangeFileName(fileName) {
this.props.setAttributes({
fileName
});
}
onChangeDownloadButtonText(downloadButtonText) {
this.props.setAttributes({
downloadButtonText
});
}
onChangeDownloadButtonVisibility(showDownloadButton) {
this.props.setAttributes({
showDownloadButton
});
}
onChangeLinkDestinationOption(newHref) {
// Choose Media File or Attachment Page (when file is in Media Library)
this.props.setAttributes({
textLinkHref: newHref
});
}
onCopyURL() {
if (this.state.isUrlCopied) {
return;
}
const {
href
} = this.props.attributes;
_clipboard.default.setString(href);
this.setState({
isUrlCopied: true
});
this.timerRef = setTimeout(() => {
this.setState({
isUrlCopied: false
});
}, URL_COPIED_NOTIFICATION_DURATION_MS);
}
onChangeOpenInNewWindow(newValue) {
this.props.setAttributes({
textLinkTarget: newValue ? '_blank' : false
});
}
updateMediaProgress(payload) {
const {
setAttributes
} = this.props;
if (payload.mediaUrl) {
setAttributes({
url: payload.mediaUrl
});
}
if (!this.state.isUploadInProgress) {
this.setState({
isUploadInProgress: true
});
}
}
finishMediaUploadWithSuccess(payload) {
const {
setAttributes
} = this.props;
setAttributes({
href: payload.mediaUrl,
id: payload.mediaServerId,
textLinkHref: payload.mediaUrl
});
this.setState({
isUploadInProgress: false
});
}
finishMediaUploadWithFailure(payload) {
this.props.setAttributes({
id: payload.mediaId
});
this.setState({
isUploadInProgress: false
});
}
mediaUploadStateReset() {
const {
setAttributes
} = this.props;
setAttributes({
id: null,
href: null,
textLinkHref: null,
fileName: null
});
this.setState({
isUploadInProgress: false
});
}
onShowLinkSettings() {
this.setState({
isSidebarLinkSettings: true
}, this.props.openSidebar);
}
getToolbarEditButton(open) {
return (0, _element.createElement)(_blockEditor.BlockControls, null, (0, _element.createElement)(_components.ToolbarGroup, null, (0, _element.createElement)(_components.ToolbarButton, {
title: (0, _i18n.__)('Edit file'),
icon: _icons.replace,
onClick: open
}), (0, _element.createElement)(_components.ToolbarButton, {
title: (0, _i18n.__)('Link To'),
icon: _icons.link,
onClick: this.onShowLinkSettings
})));
}
getInspectorControls(_ref, media, isUploadInProgress, isUploadFailed) {
let {
showDownloadButton,
textLinkTarget,
href,
textLinkHref
} = _ref;
let linkDestinationOptions = [{
value: href,
label: (0, _i18n.__)('URL')
}];
const attachmentPage = media && media.link;
const {
isSidebarLinkSettings
} = this.state;
if (attachmentPage) {
linkDestinationOptions = [{
value: href,
label: (0, _i18n.__)('Media file')
}, {
value: attachmentPage,
label: (0, _i18n.__)('Attachment page')
}];
}
const actionButtonStyle = this.props.getStylesFromColorScheme(_style.default.actionButton, _style.default.actionButtonDark);
const isCopyUrlDisabled = isUploadFailed || isUploadInProgress;
const dimmedActionButtonStyle = this.props.getStylesFromColorScheme(_style.default.dimmedActionButton, _style.default.dimmedActionButtonDark);
const finalButtonStyle = isCopyUrlDisabled ? dimmedActionButtonStyle : actionButtonStyle;
return (0, _element.createElement)(_blockEditor.InspectorControls, null, isSidebarLinkSettings || (0, _element.createElement)(_components.PanelBody, {
title: (0, _i18n.__)('File block settings')
}), (0, _element.createElement)(_components.PanelBody, null, (0, _element.createElement)(_components.SelectControl, {
icon: _icons.link,
label: (0, _i18n.__)('Link to'),
value: textLinkHref,
onChange: this.onChangeLinkDestinationOption,
options: linkDestinationOptions,
hideCancelButton: true
}), (0, _element.createElement)(_components.ToggleControl, {
icon: _icons.external,
label: (0, _i18n.__)('Open in new tab'),
checked: textLinkTarget === '_blank',
onChange: this.onChangeOpenInNewWindow
}), !isSidebarLinkSettings && (0, _element.createElement)(_components.ToggleControl, {
icon: _icons.button,
label: (0, _i18n.__)('Show download button'),
checked: showDownloadButton,
onChange: this.onChangeDownloadButtonVisibility
}), (0, _element.createElement)(_components.TextControl, {
disabled: isCopyUrlDisabled,
label: this.state.isUrlCopied ? (0, _i18n.__)('Copied!') : (0, _i18n.__)('Copy file URL'),
labelStyle: this.state.isUrlCopied || finalButtonStyle,
onPress: this.onCopyURL
})));
}
getStyleForAlignment(align) {
const getFlexAlign = alignment => {
switch (alignment) {
case 'right':
return 'flex-end';
case 'center':
return 'center';
default:
return 'flex-start';
}
};
return {
alignSelf: getFlexAlign(align)
};
}
getTextAlignmentForAlignment(align) {
switch (align) {
case 'right':
return 'right';
case 'center':
return 'center';
default:
return 'left';
}
}
onFilePressed() {
const {
attributes
} = this.props;
if (this.state.isUploadInProgress) {
(0, _reactNativeBridge.requestImageUploadCancelDialog)(attributes.id);
} else if (attributes.id && (0, _url.getProtocol)(attributes.href) === 'file:') {
(0, _reactNativeBridge.requestImageFailedRetryDialog)(attributes.id);
}
}
onLayout(_ref2) {
let {
nativeEvent
} = _ref2;
const {
width
} = nativeEvent.layout;
const {
paddingLeft,
paddingRight
} = _style.default.defaultButton;
this.setState({
maxWidth: width - (paddingLeft + paddingRight)
});
} // Render `Text` with `placeholderText` styled as a placeholder
// to calculate its width which then is set as a `minWidth`
// This should be fixed on RNAztec level. In the mean time,
// We use the same strategy implemented in Button block.
getPlaceholderWidth(placeholderText) {
const {
maxWidth,
placeholderTextWidth
} = this.state;
return (0, _element.createElement)(_reactNative.Text, {
style: _style.default.placeholder,
onTextLayout: _ref3 => {
let {
nativeEvent
} = _ref3;
const textWidth = nativeEvent.lines[0] && nativeEvent.lines[0].width;
if (textWidth && textWidth !== placeholderTextWidth) {
this.setState({
placeholderTextWidth: Math.min(textWidth, maxWidth)
});
}
}
}, placeholderText);
}
getFileComponent(openMediaOptions, getMediaOptions) {
const {
attributes,
media,
isSelected
} = this.props;
const {
isButtonFocused,
placeholderTextWidth
} = this.state;
const {
fileName,
downloadButtonText,
id,
showDownloadButton,
align
} = attributes;
const minWidth = isButtonFocused || !isButtonFocused && downloadButtonText && downloadButtonText !== '' ? MIN_WIDTH : placeholderTextWidth;
const placeholderText = isButtonFocused || !isButtonFocused && downloadButtonText && downloadButtonText !== '' ? '' : (0, _i18n.__)('Add text…');
return (0, _element.createElement)(_blockEditor.MediaUploadProgress, {
mediaId: id,
onUpdateMediaProgress: this.updateMediaProgress,
onFinishMediaUploadWithSuccess: this.finishMediaUploadWithSuccess,
onFinishMediaUploadWithFailure: this.finishMediaUploadWithFailure,
onMediaUploadStateReset: this.mediaUploadStateReset,
renderContent: _ref4 => {
let {
isUploadInProgress,
isUploadFailed
} = _ref4;
const dimmedStyle = (this.state.isUploadInProgress || isUploadFailed) && _style.default.disabledButton;
const finalButtonStyle = [_style.default.defaultButton, dimmedStyle];
const errorIconStyle = Object.assign({}, _style.default.errorIcon, _style.default.uploadFailed);
return (0, _element.createElement)(_reactNative.TouchableWithoutFeedback, {
accessible: !isSelected,
onPress: this.onFilePressed,
disabled: !isSelected
}, (0, _element.createElement)(_reactNative.View, {
onLayout: this.onLayout,
testID: "file-edit-container"
}, this.getPlaceholderWidth(placeholderText), isUploadInProgress || this.getToolbarEditButton(openMediaOptions), getMediaOptions(), isSelected && this.getInspectorControls(attributes, media, isUploadInProgress, isUploadFailed), (0, _element.createElement)(_reactNative.View, {
style: _style.default.container
}, (0, _element.createElement)(_blockEditor.RichText, {
withoutInteractiveFormatting: true,
__unstableMobileNoFocusOnMount: true,
onChange: this.onChangeFileName,
placeholder: (0, _i18n.__)('File name'),
rootTagsToEliminate: ['p'],
tagName: "p",
underlineColorAndroid: "transparent",
value: fileName,
deleteEnter: true,
textAlign: this.getTextAlignmentForAlignment(align)
}), isUploadFailed && (0, _element.createElement)(_reactNative.View, {
style: _style.default.errorContainer
}, (0, _element.createElement)(_components.Icon, {
icon: _icons.warning,
style: errorIconStyle
}), (0, _element.createElement)(_blockEditor.PlainText, {
editable: false,
value: (0, _i18n.__)('Error'),
style: _style.default.uploadFailed
}))), showDownloadButton && this.state.maxWidth > 0 && (0, _element.createElement)(_reactNative.View, {
style: [finalButtonStyle, this.getStyleForAlignment(align)]
}, (0, _element.createElement)(_blockEditor.RichText, {
withoutInteractiveFormatting: true,
__unstableMobileNoFocusOnMount: true,
rootTagsToEliminate: ['p'],
tagName: "p",
textAlign: "center",
minWidth: minWidth,
maxWidth: this.state.maxWidth,
deleteEnter: true,
style: _style.default.buttonText,
value: downloadButtonText,
placeholder: placeholderText,
unstableOnFocus: () => this.setState({
isButtonFocused: true
}),
onBlur: () => this.setState({
isButtonFocused: false
}),
selectionColor: _style.default.buttonText.color,
placeholderTextColor: _style.default.placeholderTextColor.color,
underlineColorAndroid: "transparent",
onChange: this.onChangeDownloadButtonText
}))));
}
});
}
render() {
const {
attributes,
wasBlockJustInserted,
isSelected
} = this.props;
const {
href
} = attributes;
if (!href) {
return (0, _element.createElement)(_blockEditor.MediaPlaceholder, {
icon: (0, _element.createElement)(_blockEditor.BlockIcon, {
icon: _icons.file
}),
labels: {
title: (0, _i18n.__)('File'),
instructions: (0, _i18n.__)('CHOOSE A FILE')
},
onSelect: this.onSelectFile,
onFocus: this.props.onFocus,
allowedTypes: [_blockEditor.MEDIA_TYPE_ANY],
autoOpenMediaUpload: isSelected && wasBlockJustInserted
});
}
return (0, _element.createElement)(_blockEditor.MediaUpload, {
allowedTypes: [_blockEditor.MEDIA_TYPE_ANY],
isReplacingMedia: true,
onSelect: this.onSelectFile,
render: _ref5 => {
let {
open,
getMediaOptions
} = _ref5;
return this.getFileComponent(open, getMediaOptions);
}
});
}
}
exports.FileEdit = FileEdit;
var _default = (0, _compose.compose)([(0, _data.withSelect)((select, props) => {
const {
attributes,
isSelected,
clientId
} = props;
const {
id,
href
} = attributes;
const {
isEditorSidebarOpened
} = select('core/edit-post');
const isNotFileHref = id && (0, _url.getProtocol)(href) !== 'file:';
return {
media: isNotFileHref ? select(_coreData.store).getMedia(id) : undefined,
isSidebarOpened: isSelected && isEditorSidebarOpened(),
wasBlockJustInserted: select(_blockEditor.store).wasBlockJustInserted(clientId, 'inserter_menu')
};
}), (0, _data.withDispatch)(dispatch => {
const {
openGeneralSidebar
} = dispatch('core/edit-post');
return {
openSidebar: () => openGeneralSidebar('edit-post/block')
};
}), _compose.withPreferredColorScheme])(FileEdit);
exports.default = _default;
//# sourceMappingURL=edit.native.js.map