UNPKG

@atlaskit/renderer

Version:
415 lines (412 loc) • 18.8 kB
import _extends from "@babel/runtime/helpers/extends"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/inherits"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import _regeneratorRuntime from "@babel/runtime/regenerator"; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } import React, { Component, useContext } from 'react'; import { filter } from '@atlaskit/adf-utils/traverse'; import { Card as CardAsync, CardSync, CardLoading, CardError } from '@atlaskit/media-card'; import { MediaClientContext } from '@atlaskit/media-client-react'; import { withImageLoader } from '@atlaskit/editor-common/utils'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import AnalyticsContext from '../analytics/analyticsContext'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics'; export var mediaIdentifierMap = new Map(); export var getListOfIdentifiersFromDoc = function getListOfIdentifiersFromDoc(doc) { if (!doc) { return []; } return filter(doc, function (node) { return node.type === 'media'; }).reduce(function (identifierList, mediaNode) { if (mediaNode.attrs) { var _mediaNode$attrs = mediaNode.attrs, type = _mediaNode$attrs.type, dataURI = _mediaNode$attrs.url, id = _mediaNode$attrs.id; if (type === 'file' && id) { identifierList.push({ mediaItemType: 'file', id: id }); } else if (type === 'external' && dataURI) { identifierList.push({ mediaItemType: 'external-image', dataURI: dataURI, name: dataURI }); } } return identifierList; }, []); }; // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/react/no-class-components export var MediaCardView = /*#__PURE__*/function (_Component) { function MediaCardView() { var _this; _classCallCheck(this, MediaCardView); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, MediaCardView, [].concat(args)); _defineProperty(_this, "state", {}); _defineProperty(_this, "saveFileState", /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(id) { var _this$props, collectionName, mediaClient, options, fileState, _t; return _regeneratorRuntime.wrap(function (_context) { while (1) switch (_context.prev = _context.next) { case 0: _this$props = _this.props, collectionName = _this$props.collection, mediaClient = _this$props.mediaClient; options = { collectionName: collectionName }; _context.prev = 1; if (!mediaClient) { _context.next = 3; break; } _context.next = 2; return mediaClient.file.getCurrentState(id, options); case 2: fileState = _context.sent; _this.setState({ fileState: fileState }); case 3: _context.next = 5; break; case 4: _context.prev = 4; _t = _context["catch"](1); case 5: case "end": return _context.stop(); } }, _callee, null, [[1, 4]]); })); return function (_x) { return _ref.apply(this, arguments); }; }()); _defineProperty(_this, "onError", function (reason) { var _this$props$fireAnaly, _this$props3; var _this$props2 = _this.props, nestedUnder = _this$props2.nestedUnder, rendererContext = _this$props2.rendererContext; (_this$props$fireAnaly = (_this$props3 = _this.props).fireAnalyticsEvent) === null || _this$props$fireAnaly === void 0 || _this$props$fireAnaly.call(_this$props3, { action: ACTION.ERRORED, actionSubject: ACTION_SUBJECT.RENDERER, actionSubjectId: ACTION_SUBJECT_ID.MEDIA, eventType: EVENT_TYPE.UI, attributes: _objectSpread(_objectSpread({ reason: reason, external: false }, nestedUnder && editorExperiment('platform_synced_block', true) ? { nestedUnder: nestedUnder } : {}), rendererContext !== null && rendererContext !== void 0 && rendererContext.nestedRendererType && editorExperiment('platform_synced_block', true) ? { nestedRendererType: rendererContext.nestedRendererType } : {}) }); }); _defineProperty(_this, "renderLoadingCard", function () { var cardDimensions = _this.props.cardDimensions; return /*#__PURE__*/React.createElement(CardLoading, { dimensions: cardDimensions, interactionName: "renderer-media-card-loading" }); }); /** * We want to call provided `eventHandlers.media.onClick` when it's provided, * but we also don't want to call it when it's a video and inline video player is enabled. * This is due to consumers normally process this onClick call by opening media viewer and * we don't want that to happened described above text. */ _defineProperty(_this, "getOnCardClickCallback", function (isInlinePlayer) { var eventHandlers = _this.props.eventHandlers; if (eventHandlers && eventHandlers.media && eventHandlers.media.onClick) { return function (result, analyticsEvent) { var isVideo = result.mediaItemDetails && result.mediaItemDetails.mediaType === 'video'; var isVideoWithInlinePlayer = isInlinePlayer && isVideo; if (!isVideoWithInlinePlayer && eventHandlers && eventHandlers.media && eventHandlers.media.onClick) { eventHandlers.media.onClick(result, analyticsEvent); } }; } return undefined; }); return _this; } _inherits(MediaCardView, _Component); return _createClass(MediaCardView, [{ key: "componentDidMount", value: function () { var _componentDidMount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() { var _this$props4, rendererContext, contextIdentifierProvider, id, url, collectionName, nodeIsInCache, _t2, _t3; return _regeneratorRuntime.wrap(function (_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: _this$props4 = this.props, rendererContext = _this$props4.rendererContext, contextIdentifierProvider = _this$props4.contextIdentifierProvider, id = _this$props4.id, url = _this$props4.url, collectionName = _this$props4.collection; if (!contextIdentifierProvider) { _context2.next = 2; break; } _t2 = this; _context2.next = 1; return contextIdentifierProvider; case 1: _t3 = _context2.sent; _t2.setState.call(_t2, { contextIdentifierProvider: _t3 }); case 2: nodeIsInCache = id && mediaIdentifierMap.has(id) || url && mediaIdentifierMap.has(url); if (rendererContext && rendererContext.adDoc && !nodeIsInCache) { getListOfIdentifiersFromDoc(rendererContext.adDoc).forEach(function (identifier) { if (identifier.mediaItemType === 'file' && identifier.id === id) { mediaIdentifierMap.set(identifier.id, _objectSpread(_objectSpread({}, identifier), {}, { collectionName: collectionName })); } else if (identifier.mediaItemType === 'external-image') { mediaIdentifierMap.set(identifier.dataURI, identifier); } }); } if (id) { this.saveFileState(id); } case 3: case "end": return _context2.stop(); } }, _callee2, this); })); function componentDidMount() { return _componentDidMount.apply(this, arguments); } return componentDidMount; }() }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var oldId = prevProps.id; if (this.props.id && oldId !== this.props.id) { this.saveFileState(this.props.id); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this$props5 = this.props, id = _this$props5.id, dataURI = _this$props5.url; if (id) { mediaIdentifierMap.delete(id); } else if (dataURI) { mediaIdentifierMap.delete(dataURI); } } }, { key: "renderExternal", value: function renderExternal(shouldOpenMediaViewer) { var _this$props6 = this.props, cardDimensions = _this$props6.cardDimensions, resizeMode = _this$props6.resizeMode, appearance = _this$props6.appearance, url = _this$props6.url, imageStatus = _this$props6.imageStatus, disableOverlay = _this$props6.disableOverlay, alt = _this$props6.alt, featureFlags = _this$props6.featureFlags, ssr = _this$props6.ssr, mediaClient = _this$props6.mediaClient, dataAttributes = _this$props6.dataAttributes, enableSyncMediaCard = _this$props6.enableSyncMediaCard, localId = _this$props6.localId; if (imageStatus === 'loading' || !url) { return this.renderLoadingCard(); } var identifier = { dataURI: url, name: url, mediaItemType: 'external-image' }; // we need this statement for the mandatory mediaClientConfig below var mediaClientConfig = mediaClient === null || mediaClient === void 0 ? void 0 : mediaClient.mediaClientConfig; var Card = enableSyncMediaCard ? CardSync : CardAsync; return ( /*#__PURE__*/ // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading React.createElement("div", _extends({}, dataAttributes, { "data-node-type": "media", "data-local-id": localId }), /*#__PURE__*/React.createElement(Card // TODO: MPT-315 - clean up after we move mediaClientConfig into FileIdentifier // context is not really used when the type is external and we want to render the component asap // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , { mediaClientConfig: mediaClientConfig, alt: alt, identifier: identifier, dimensions: cardDimensions, appearance: appearance, resizeMode: resizeMode, disableOverlay: disableOverlay, shouldOpenMediaViewer: shouldOpenMediaViewer, mediaViewerItems: Array.from(mediaIdentifierMap.values()), featureFlags: featureFlags, ssr: ssr === null || ssr === void 0 ? void 0 : ssr.mode, shouldHideTooltip: false, onError: expValEquals('platform_editor_media_error_analytics', 'isEnabled', true) ? this.onError : undefined })) ); } }, { key: "render", value: function render() { var _this$state = this.state, contextIdentifierProvider = _this$state.contextIdentifierProvider, fileState = _this$state.fileState; var _this$props7 = this.props, id = _this$props7.id, alt = _this$props7.alt, type = _this$props7.type, collection = _this$props7.collection, occurrenceKey = _this$props7.occurrenceKey, cardDimensions = _this$props7.cardDimensions, resizeMode = _this$props7.resizeMode, disableOverlay = _this$props7.disableOverlay, useInlinePlayer = _this$props7.useInlinePlayer, originalDimensions = _this$props7.originalDimensions, forceOpenMediaViewer = _this$props7.shouldOpenMediaViewer, featureFlags = _this$props7.featureFlags, shouldEnableDownloadButton = _this$props7.shouldEnableDownloadButton, ssr = _this$props7.ssr, mediaClient = _this$props7.mediaClient, dataAttributes = _this$props7.dataAttributes, enableSyncMediaCard = _this$props7.enableSyncMediaCard, localId = _this$props7.localId, mediaViewerExtensions = _this$props7.mediaViewerExtensions; var isMobile = false; var shouldPlayInline = useInlinePlayer !== undefined ? useInlinePlayer : true; var isInlinePlayer = isMobile ? false : shouldPlayInline; var onCardClick = this.getOnCardClickCallback(isInlinePlayer); var shouldOpenMediaViewer = typeof forceOpenMediaViewer === 'boolean' ? forceOpenMediaViewer : !isMobile && !onCardClick; if (type === 'external') { return this.renderExternal(shouldOpenMediaViewer); } if (type === 'link') { return null; } var mediaClientConfig = !!ssr ? ssr.config : mediaClient === null || mediaClient === void 0 ? void 0 : mediaClient.mediaClientConfig; if (!mediaClientConfig || !id) { return this.renderLoadingCard(); } if (!id || type !== 'file') { return /*#__PURE__*/React.createElement(CardError, { dimensions: cardDimensions }); } var contextId = contextIdentifierProvider && contextIdentifierProvider.objectId; var identifier = { id: id, mediaItemType: 'file', collectionName: collection, occurrenceKey: occurrenceKey }; var Card = enableSyncMediaCard ? CardSync : CardAsync; // Quick solution to disable lazy loading of images on PDF export pages in Confluence to remedy an issue with images never loading // More robust solution will be implemented as part of CCPDF-233 - Link: https://hello.jira.atlassian.cloud/browse/CCPDF-233 var currentUrl = window.location.href; var shouldDisableLazyLoading = expValEquals('platform_editor_disable_lazy_load_media', 'isEnabled', true) && currentUrl.includes('/wiki/pdf/spaces/'); return /*#__PURE__*/React.createElement("div", _extends({}, getClipboardAttrs({ id: id, alt: alt, collection: collection, contextIdentifierProvider: contextIdentifierProvider, originalDimensions: originalDimensions, fileState: fileState }), dataAttributes, { "data-local-id": localId }), /*#__PURE__*/React.createElement(Card, { identifier: identifier, alt: alt, contextId: contextId, mediaClientConfig: mediaClientConfig, dimensions: cardDimensions, originalDimensions: originalDimensions, onClick: onCardClick, resizeMode: resizeMode, isLazy: !isMobile && !shouldDisableLazyLoading, disableOverlay: disableOverlay, useInlinePlayer: isInlinePlayer, shouldOpenMediaViewer: shouldOpenMediaViewer, mediaViewerItems: Array.from(mediaIdentifierMap.values()), featureFlags: featureFlags, shouldEnableDownloadButton: shouldEnableDownloadButton, ssr: ssr === null || ssr === void 0 ? void 0 : ssr.mode, shouldHideTooltip: isMobile, mediaViewerExtensions: mediaViewerExtensions, onError: expValEquals('platform_editor_media_error_analytics', 'isEnabled', true) ? this.onError : undefined })); } }]); }(Component); // Needed for copy & paste export var getClipboardAttrs = function getClipboardAttrs(_ref2) { var id = _ref2.id, alt = _ref2.alt, collection = _ref2.collection, contextIdentifierProvider = _ref2.contextIdentifierProvider, originalDimensions = _ref2.originalDimensions, fileState = _ref2.fileState; var contextId = contextIdentifierProvider && contextIdentifierProvider.objectId; var width = originalDimensions && originalDimensions.width; var height = originalDimensions && originalDimensions.height; var fileName = 'file'; // default name is needed for Confluence var fileSize = 1; var fileMimeType = ''; if (fileState && fileState.status !== 'error') { fileSize = fileState.size; fileName = fileState.name; fileMimeType = fileState.mimeType; } return { 'data-context-id': contextId, 'data-type': 'file', 'data-node-type': 'media', 'data-width': width, 'data-height': height, 'data-id': id, 'data-collection': collection, 'data-file-name': fileName, 'data-file-size': fileSize, 'data-file-mime-type': fileMimeType, 'data-alt': alt }; }; export var MediaCardInternal = function MediaCardInternal(props) { var mediaClient = useContext(MediaClientContext); return /*#__PURE__*/React.createElement(AnalyticsContext.Consumer, null, function (_ref3) { var fireAnalyticsEvent = _ref3.fireAnalyticsEvent; return /*#__PURE__*/React.createElement(MediaCardView // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , _extends({}, props, { mediaClient: mediaClient, fireAnalyticsEvent: fireAnalyticsEvent })); }); }; export var MediaCard = withImageLoader(MediaCardInternal);