@atlaskit/editor-plugin-media
Version:
Media plugin for @atlaskit/editor-core
182 lines (179 loc) • 7.33 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import React, { Component } from 'react';
import { MEDIA_CONTEXT } from '@atlaskit/analytics-namespaced-context';
import { AnalyticsContext } from '@atlaskit/analytics-next';
import { setNodeSelection, setTextSelection, withImageLoader } from '@atlaskit/editor-common/utils';
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
import { Card, CardLoading } from '@atlaskit/media-card';
import { stateKey as mediaStateKey } from '../../pm-plugins/plugin-key';
import { MediaCardWrapper } from '../styles';
// This is being used by DropPlaceholder now
export const MEDIA_HEIGHT = 125;
export const FILE_WIDTH = 156;
// eslint-disable-next-line @repo/internal/react/no-class-components
export class MediaNode extends Component {
constructor(_props) {
super(_props);
_defineProperty(this, "state", {});
_defineProperty(this, "setViewMediaClientConfig", async () => {
const mediaProvider = await this.props.mediaProvider;
if (mediaProvider) {
const viewMediaClientConfig = mediaProvider.viewMediaClientConfig;
this.setState({
viewMediaClientConfig
});
}
});
_defineProperty(this, "selectMediaSingleFromCard", ({
event
}) => {
this.selectMediaSingle(event);
});
_defineProperty(this, "selectMediaSingle", event => {
const propPos = this.props.getPos();
if (typeof propPos !== 'number') {
return;
}
// We need to call "stopPropagation" here in order to prevent the browser from navigating to
// another URL if the media node is wrapped in a link mark.
event.stopPropagation();
const {
state
} = this.props.view;
if (event.shiftKey) {
// don't select text if there is current selection in a table (as this would override selected cells)
if (state.selection instanceof CellSelection) {
return;
}
setTextSelection(this.props.view, state.selection.from < propPos ? state.selection.from : propPos - 1,
// + 3 needed for offset of the media inside mediaSingle and cursor to make whole mediaSingle selected
state.selection.to > propPos ? state.selection.to : propPos + 2);
} else {
setNodeSelection(this.props.view, propPos - 1);
}
});
_defineProperty(this, "onFullscreenChange", fullscreen => {
var _this$mediaPluginStat;
(_this$mediaPluginStat = this.mediaPluginState) === null || _this$mediaPluginStat === void 0 ? void 0 : _this$mediaPluginStat.updateAndDispatch({
isFullscreen: fullscreen
});
});
_defineProperty(this, "handleNewNode", props => {
var _this$mediaPluginStat2;
const {
node
} = props;
(_this$mediaPluginStat2 = this.mediaPluginState) === null || _this$mediaPluginStat2 === void 0 ? void 0 : _this$mediaPluginStat2.handleMediaNodeMount(node, () => this.props.getPos());
});
const {
view
} = this.props;
this.mediaPluginState = mediaStateKey.getState(view.state);
}
shouldComponentUpdate(nextProps, nextState) {
const hasNewViewMediaClientConfig = !this.state.viewMediaClientConfig && nextState.viewMediaClientConfig;
if (this.props.selected !== nextProps.selected || this.props.node.attrs.id !== nextProps.node.attrs.id || this.props.node.attrs.collection !== nextProps.node.attrs.collection || this.props.maxDimensions.height !== nextProps.maxDimensions.height || this.props.maxDimensions.width !== nextProps.maxDimensions.width || this.props.contextIdentifierProvider !== nextProps.contextIdentifierProvider || this.props.isLoading !== nextProps.isLoading || this.props.mediaProvider !== nextProps.mediaProvider || hasNewViewMediaClientConfig) {
return true;
}
return false;
}
async componentDidMount() {
this.handleNewNode(this.props);
const {
contextIdentifierProvider
} = this.props;
this.setState({
contextIdentifierProvider: await contextIdentifierProvider
});
await this.setViewMediaClientConfig();
}
componentWillUnmount() {
var _this$mediaPluginStat3;
const {
node
} = this.props;
(_this$mediaPluginStat3 = this.mediaPluginState) === null || _this$mediaPluginStat3 === void 0 ? void 0 : _this$mediaPluginStat3.handleMediaNodeUnmount(node);
}
componentDidUpdate(prevProps) {
var _this$mediaPluginStat5;
if (prevProps.node.attrs.id !== this.props.node.attrs.id) {
var _this$mediaPluginStat4;
(_this$mediaPluginStat4 = this.mediaPluginState) === null || _this$mediaPluginStat4 === void 0 ? void 0 : _this$mediaPluginStat4.handleMediaNodeUnmount(prevProps.node);
this.handleNewNode(this.props);
}
(_this$mediaPluginStat5 = this.mediaPluginState) === null || _this$mediaPluginStat5 === void 0 ? void 0 : _this$mediaPluginStat5.updateElement();
this.setViewMediaClientConfig();
}
render() {
const {
node,
selected,
originalDimensions,
isLoading,
maxDimensions,
mediaOptions
} = this.props;
const borderMark = node.marks.find(m => m.type.name === 'border');
const {
viewMediaClientConfig,
contextIdentifierProvider
} = this.state;
const {
id,
type,
collection,
url,
alt
} = node.attrs;
if (isLoading || type !== 'external' && !viewMediaClientConfig) {
return /*#__PURE__*/React.createElement(MediaCardWrapper, {
dimensions: originalDimensions
}, /*#__PURE__*/React.createElement(CardLoading, null));
}
const contextId = contextIdentifierProvider && contextIdentifierProvider.objectId;
const identifier = type === 'external' ? {
dataURI: url,
name: url,
mediaItemType: 'external-image'
} : {
id,
mediaItemType: 'file',
collectionName: collection
};
// mediaClientConfig is not needed for "external" case. So we have to cheat here.
// there is a possibility mediaClientConfig will be part of a identifier,
// so this might be not an issue
const mediaClientConfig = viewMediaClientConfig || {
authProvider: () => ({})
};
return /*#__PURE__*/React.createElement(MediaCardWrapper, {
dimensions: originalDimensions,
onContextMenu: this.selectMediaSingle,
borderWidth: borderMark === null || borderMark === void 0 ? void 0 : borderMark.attrs.size,
selected: selected
}, /*#__PURE__*/React.createElement(AnalyticsContext, {
data: {
[MEDIA_CONTEXT]: {
border: !!borderMark
}
}
}, /*#__PURE__*/React.createElement(Card, {
mediaClientConfig: mediaClientConfig,
resizeMode: "stretchy-fit",
dimensions: maxDimensions,
originalDimensions: originalDimensions,
identifier: identifier,
selectable: true,
selected: selected,
disableOverlay: true,
onFullscreenChange: this.onFullscreenChange,
onClick: this.selectMediaSingleFromCard,
useInlinePlayer: mediaOptions && mediaOptions.allowLazyLoading,
isLazy: mediaOptions && mediaOptions.allowLazyLoading,
featureFlags: mediaOptions && mediaOptions.featureFlags,
contextId: contextId,
alt: alt
})));
}
}
export default withImageLoader(MediaNode);