UNPKG

@wordpress/components

Version:
281 lines (275 loc) 11.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _reactNative = require("react-native"); var _reactNativeFastImage = _interopRequireDefault(require("react-native-fast-image")); var _i18n = require("@wordpress/i18n"); var _icons = require("@wordpress/icons"); var _compose = require("@wordpress/compose"); var _element = require("@wordpress/element"); var _utils = require("./utils"); var _style = _interopRequireDefault(require("./style.scss")); var _iconRetry = _interopRequireDefault(require("./icon-retry")); var _imageEditingButton = _interopRequireDefault(require("./image-editing-button")); var _icon = _interopRequireDefault(require("../../icon")); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const ICON_TYPE = { OFFLINE: 'offline', PLACEHOLDER: 'placeholder', RETRY: 'retry', UPLOAD: 'upload' }; const ImageComponent = ({ align, alt, editButton = true, focalPoint, height: imageHeight, highlightSelected = true, isSelected, shouldUseFastImage, isUploadFailed, isUploadPaused, isUploadInProgress, mediaPickerOptions, onImageDataLoad, onSelectMediaUploadOption, openMediaOptions, resizeMode, retryMessage, retryIcon, url, shapeStyle, style, width: imageWidth }) => { const [imageData, setImageData] = (0, _element.useState)(null); const [containerSize, setContainerSize] = (0, _element.useState)(null); const [localURL, setLocalURL] = (0, _element.useState)(null); const [networkURL, setNetworkURL] = (0, _element.useState)(null); const [networkImageLoaded, setNetworkImageLoaded] = (0, _element.useState)(false); // Disabled for Android due to https://github.com/WordPress/gutenberg/issues/43149 const Image = !shouldUseFastImage || _element.Platform.isAndroid ? _reactNative.Image : _reactNativeFastImage.default; const imageResizeMode = !shouldUseFastImage || _element.Platform.isAndroid ? resizeMode : _reactNativeFastImage.default.resizeMode[resizeMode]; (0, _element.useEffect)(() => { let isCurrent = true; if (url) { _reactNative.Image.getSize(url, (imgWidth, imgHeight) => { if (!isCurrent) { return; } const metaData = { aspectRatio: imgWidth / imgHeight, width: imgWidth, height: imgHeight }; setImageData(metaData); if (onImageDataLoad) { onImageDataLoad(metaData); } }); if (url.startsWith('file:///')) { setLocalURL(url); setNetworkURL(null); setNetworkImageLoaded(false); } else if (url.startsWith('https://')) { if (_element.Platform.isIOS) { setNetworkURL(url); } else if (_element.Platform.isAndroid) { _reactNative.Image.prefetch(url).then(() => { if (!isCurrent) { return; } setNetworkURL(url); setNetworkImageLoaded(true); }, () => { // This callback is called when the image fails to load, // but these events are handled by `isUploadFailed` // and `isUploadPaused` events instead. // // Ignoring the error event will persist the local image URI. }); } } } return () => isCurrent = false; // See https://github.com/WordPress/gutenberg/pull/41166 }, [url]); const onContainerLayout = event => { const { height, width } = event.nativeEvent.layout; if (width !== 0 && height !== 0 && (containerSize?.width !== width || containerSize?.height !== height)) { setContainerSize({ width, height }); } }; const getIcon = iconType => { let icon; let iconStyle; switch (iconType) { case ICON_TYPE.RETRY: icon = retryIcon || _iconRetry.default; iconStyle = iconRetryStyles; break; case ICON_TYPE.OFFLINE: icon = _icons.offline; iconStyle = iconOfflineStyles; break; case ICON_TYPE.PLACEHOLDER: icon = _icons.image; iconStyle = iconPlaceholderStyles; break; case ICON_TYPE.UPLOAD: icon = _icons.image; iconStyle = iconUploadStyles; break; } return /*#__PURE__*/(0, _jsxRuntime.jsx)(_icon.default, { icon: icon, ...iconStyle }); }; const iconPlaceholderStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.iconPlaceholder, _style.default.iconPlaceholderDark); const iconUploadStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.iconUpload, _style.default.iconUploadDark); const iconOfflineStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.iconOffline, _style.default.iconOfflineDark); const retryIconStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.retryIcon, _style.default.retryIconDark); const iconRetryStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.iconRetry, _style.default.iconRetryDark); const retryContainerStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.retryContainer, _style.default.retryContainerDark); const uploadFailedTextStyles = (0, _compose.usePreferredColorSchemeStyle)(_style.default.uploadFailedText, _style.default.uploadFailedTextDark); const placeholderStyles = [(0, _compose.usePreferredColorSchemeStyle)(_style.default.imageContainerUpload, _style.default.imageContainerUploadDark), focalPoint && _style.default.imageContainerUploadWithFocalpoint, imageHeight && { height: imageHeight }]; const customWidth = imageData?.width < containerSize?.width ? imageData?.width : _style.default.wide?.width; const imageContainerStyles = [_style.default.imageContent, { width: imageWidth === _style.default.wide?.width || imageData && imageWidth > 0 && imageWidth < containerSize?.width ? imageWidth : customWidth }, resizeMode && { width: _style.default.wide?.width }, focalPoint && _style.default.focalPointContainer]; const imageStyles = [{ height: containerSize?.height }, !resizeMode && { aspectRatio: imageData?.aspectRatio }, focalPoint && _style.default.focalPoint, focalPoint && (0, _utils.getImageWithFocalPointStyles)(focalPoint, containerSize, imageData), !focalPoint && imageData && containerSize && { height: imageData?.width > containerSize?.width && !imageWidth ? containerSize?.width / imageData?.aspectRatio : undefined }, imageHeight && { height: imageHeight }, shapeStyle]; // On iOS, add 1 to height to account for the 1px non-visible image // that is used to determine when the network image has loaded // We also must verify that it is not NaN, as it can be NaN when the image is loading. // This is not necessary on Android as the non-visible image is not used. let calculatedSelectedHeight; if (_element.Platform.isIOS) { calculatedSelectedHeight = containerSize && !isNaN(containerSize.height) ? containerSize.height + 1 : 0; } else { calculatedSelectedHeight = containerSize?.height; } const imageSelectedStyles = [(0, _compose.usePreferredColorSchemeStyle)(_style.default.imageBorder, _style.default.imageBorderDark), { height: calculatedSelectedHeight }]; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [_style.default.container, // Only set alignItems if an image exists because alignItems causes the placeholder // to disappear when an aligned image can't be downloaded // https://github.com/wordpress-mobile/gutenberg-mobile/issues/1592 imageData && align && { alignItems: align }, style], onLayout: onContainerLayout, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { accessible: true, disabled: !isSelected, accessibilityLabel: alt, accessibilityHint: (0, _i18n.__)('Double tap to view larger.'), accessibilityRole: "imagebutton", style: imageContainerStyles, children: [isSelected && highlightSelected && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: imageSelectedStyles }), !imageData ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: placeholderStyles, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _style.default.imageUploadingIconContainer, children: getIcon(ICON_TYPE.UPLOAD) }) }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: focalPoint && _style.default.focalPointContent, children: [_element.Platform.isAndroid && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [networkImageLoaded && networkURL && /*#__PURE__*/(0, _jsxRuntime.jsx)(Image, { style: imageStyles, fadeDuration: 0, source: { uri: networkURL }, ...(!focalPoint && { resizeMethod: 'scale' }), resizeMode: imageResizeMode, testID: `network-image-${url}` }), !networkImageLoaded && !networkURL && /*#__PURE__*/(0, _jsxRuntime.jsx)(Image, { style: imageStyles, fadeDuration: 0, source: { uri: localURL }, ...(!focalPoint && { resizeMethod: 'scale' }), resizeMode: imageResizeMode })] }), _element.Platform.isIOS && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Image, { style: imageStyles, source: { uri: networkURL && networkImageLoaded ? networkURL : localURL || url }, ...(!focalPoint && { resizeMethod: 'scale' }), resizeMode: imageResizeMode, testID: `network-image-${networkURL && networkImageLoaded ? networkURL : localURL || url}` }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Image, { source: { uri: networkURL }, style: _style.default.nonVisibleImage, onLoad: () => { setNetworkImageLoaded(true); } })] })] }), (isUploadFailed || isUploadPaused) && retryMessage && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [_style.default.imageContainer, retryContainerStyles], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [retryIconStyles, retryIcon && _style.default.customRetryIcon], children: isUploadPaused ? getIcon(ICON_TYPE.OFFLINE) : getIcon(ICON_TYPE.RETRY) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: uploadFailedTextStyles, children: retryMessage })] })] }, url), editButton && isSelected && !isUploadInProgress && /*#__PURE__*/(0, _jsxRuntime.jsx)(_imageEditingButton.default, { onSelectMediaUploadOption: onSelectMediaUploadOption, openMediaOptions: openMediaOptions, url: !(isUploadFailed || isUploadPaused) && imageData && url, pickerOptions: mediaPickerOptions })] }); }; var _default = exports.default = ImageComponent; //# sourceMappingURL=index.native.js.map