@atlaskit/editor-plugin-media 12.4.1 → 12.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/nodeviews/helpers.js +5 -1
- package/dist/cjs/nodeviews/mediaNodeUpdater.js +72 -3
- package/dist/cjs/nodeviews/mediaSingleNext.js +11 -5
- package/dist/cjs/nodeviews/nodeviewHelpers.js +26 -0
- package/dist/cjs/pm-plugins/main.js +213 -20
- package/dist/cjs/ui/toolbar/index.js +13 -1
- package/dist/es2019/nodeviews/helpers.js +5 -1
- package/dist/es2019/nodeviews/mediaNodeUpdater.js +77 -1
- package/dist/es2019/nodeviews/mediaSingleNext.js +11 -5
- package/dist/es2019/nodeviews/nodeviewHelpers.js +20 -0
- package/dist/es2019/pm-plugins/main.js +211 -4
- package/dist/es2019/ui/toolbar/index.js +13 -1
- package/dist/esm/nodeviews/helpers.js +5 -1
- package/dist/esm/nodeviews/mediaNodeUpdater.js +70 -1
- package/dist/esm/nodeviews/mediaSingleNext.js +11 -5
- package/dist/esm/nodeviews/nodeviewHelpers.js +20 -0
- package/dist/esm/pm-plugins/main.js +203 -10
- package/dist/esm/ui/toolbar/index.js +13 -1
- package/dist/types/nodeviews/mediaNodeUpdater.d.ts +3 -1
- package/dist/types/nodeviews/nodeviewHelpers.d.ts +11 -0
- package/dist/types/pm-plugins/main.d.ts +12 -0
- package/dist/types/pm-plugins/types.d.ts +3 -0
- package/dist/types-ts4.5/nodeviews/mediaNodeUpdater.d.ts +3 -1
- package/dist/types-ts4.5/nodeviews/nodeviewHelpers.d.ts +11 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +12 -0
- package/dist/types-ts4.5/pm-plugins/types.d.ts +3 -0
- package/nodeviewHelpers/package.json +17 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-media
|
|
2
2
|
|
|
3
|
+
## 12.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 12.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`76dff28130c6a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/76dff28130c6a) -
|
|
14
|
+
Add replace-media button to media plugin
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 12.4.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -5,5 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.hasPrivateAttrsChanged = void 0;
|
|
7
7
|
var hasPrivateAttrsChanged = exports.hasPrivateAttrsChanged = function hasPrivateAttrsChanged(currentAttrs, newAttrs) {
|
|
8
|
-
return currentAttrs.__fileName !== newAttrs.__fileName || currentAttrs.__fileMimeType !== newAttrs.__fileMimeType || currentAttrs.__fileSize !== newAttrs.__fileSize || currentAttrs.__contextId !== newAttrs.__contextId
|
|
8
|
+
return currentAttrs.__fileName !== newAttrs.__fileName || currentAttrs.__fileMimeType !== newAttrs.__fileMimeType || currentAttrs.__fileSize !== newAttrs.__fileSize || currentAttrs.__contextId !== newAttrs.__contextId ||
|
|
9
|
+
// A changed id means the media source was replaced — always re-initialise
|
|
10
|
+
// the updater so getRemoteDimensions fetches dimensions for the new file.
|
|
11
|
+
// Only check when id is explicitly present on the new attrs (it's Partial).
|
|
12
|
+
'id' in newAttrs && currentAttrs.id !== newAttrs.id;
|
|
9
13
|
};
|
|
@@ -12,8 +12,10 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
|
|
|
12
12
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
13
13
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
14
14
|
var _v = _interopRequireDefault(require("uuid/v4"));
|
|
15
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
15
16
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
16
17
|
var _mediaSingle = require("@atlaskit/editor-common/media-single");
|
|
18
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
17
19
|
var _mediaClient = require("@atlaskit/media-client");
|
|
18
20
|
var _mediaClientReact = require("@atlaskit/media-client-react");
|
|
19
21
|
var _mediaCommon = require("@atlaskit/media-common");
|
|
@@ -22,10 +24,11 @@ var _helpers = require("../pm-plugins/commands/helpers");
|
|
|
22
24
|
var _pluginKey = require("../pm-plugins/plugin-key");
|
|
23
25
|
var _batchMediaNodeAttrs = require("../pm-plugins/utils/batchMediaNodeAttrs");
|
|
24
26
|
var _mediaCommon2 = require("../pm-plugins/utils/media-common");
|
|
27
|
+
var _nodeviewHelpers = require("./nodeviewHelpers");
|
|
25
28
|
var _excluded = ["authProvider"],
|
|
26
|
-
_excluded2 = ["authProvider"];
|
|
29
|
+
_excluded2 = ["authProvider"];
|
|
27
30
|
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; }
|
|
28
|
-
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) { (0, _defineProperty2.default)(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; }
|
|
31
|
+
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) { (0, _defineProperty2.default)(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; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
29
32
|
var isMediaTypeSupported = function isMediaTypeSupported(type) {
|
|
30
33
|
if (type) {
|
|
31
34
|
return ['image', 'file'].includes(type);
|
|
@@ -324,7 +327,73 @@ var MediaNodeUpdater = exports.MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
324
327
|
return attrs.__contextId || null;
|
|
325
328
|
});
|
|
326
329
|
(0, _defineProperty2.default)(this, "updateDimensions", function (dimensions) {
|
|
327
|
-
|
|
330
|
+
var view = _this.props.view;
|
|
331
|
+
var mediaPluginState = _pluginKey.stateKey.getState(view.state);
|
|
332
|
+
var targetDisplayHeight = mediaPluginState === null || mediaPluginState === void 0 ? void 0 : mediaPluginState.replaceMediaTargetDisplayHeight;
|
|
333
|
+
if (targetDisplayHeight !== null && targetDisplayHeight !== undefined && dimensions.width > 0) {
|
|
334
|
+
var _this$props$lineLengt, _mediaSingleNode$attr, _mediaSingleNode;
|
|
335
|
+
// Replace mode: combine intrinsic dimension update on the media node AND
|
|
336
|
+
// display width update on the mediaSingle into a single transaction so they
|
|
337
|
+
// are never out of sync and don't cause two separate renders/layout shifts.
|
|
338
|
+
|
|
339
|
+
// Clear the stored target height — this is a one-shot adjustment
|
|
340
|
+
if (mediaPluginState) {
|
|
341
|
+
mediaPluginState.replaceMediaTargetDisplayHeight = null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Clamp to the layout's maximum width so the image never overflows its container.
|
|
345
|
+
var lineLength = (_this$props$lineLengt = _this.props.lineLength) !== null && _this$props$lineLengt !== void 0 ? _this$props$lineLengt : 760;
|
|
346
|
+
var state = view.state;
|
|
347
|
+
var mediaSingle = state.schema.nodes.mediaSingle;
|
|
348
|
+
// Typed explicitly because TypeScript can't track mutations inside
|
|
349
|
+
// the descendants callback closure and would narrow these to `never`.
|
|
350
|
+
var mediaSinglePos = null;
|
|
351
|
+
var mediaSingleNode = null;
|
|
352
|
+
var mediaPos = null;
|
|
353
|
+
state.doc.descendants(function (node, pos) {
|
|
354
|
+
if (mediaSinglePos !== null) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
if (node.type === mediaSingle) {
|
|
358
|
+
var mediaChild = node.firstChild;
|
|
359
|
+
if (mediaChild && mediaChild.attrs.id === dimensions.id) {
|
|
360
|
+
mediaSinglePos = pos;
|
|
361
|
+
mediaSingleNode = node;
|
|
362
|
+
mediaPos = pos + 1;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return true;
|
|
366
|
+
});
|
|
367
|
+
var layout = (_mediaSingleNode$attr = (_mediaSingleNode = mediaSingleNode) === null || _mediaSingleNode === void 0 || (_mediaSingleNode = _mediaSingleNode.attrs) === null || _mediaSingleNode === void 0 ? void 0 : _mediaSingleNode.layout) !== null && _mediaSingleNode$attr !== void 0 ? _mediaSingleNode$attr : 'center';
|
|
368
|
+
var newDisplayWidth = (0, _nodeviewHelpers.computeReplacementDisplayWidth)(targetDisplayHeight, dimensions.width, dimensions.height, layout, lineLength);
|
|
369
|
+
if (mediaSinglePos !== null && mediaSingleNode !== null && mediaPos !== null) {
|
|
370
|
+
var tr = state.tr;
|
|
371
|
+
|
|
372
|
+
// Update intrinsic dimensions on the media child node
|
|
373
|
+
tr.step(new _steps.SetAttrsStep(mediaPos, {
|
|
374
|
+
height: dimensions.height,
|
|
375
|
+
width: dimensions.width
|
|
376
|
+
}));
|
|
377
|
+
|
|
378
|
+
// Update display width on the mediaSingle parent
|
|
379
|
+
tr.setNodeMarkup(mediaSinglePos, undefined, _objectSpread(_objectSpread({}, mediaSingleNode.attrs), {}, {
|
|
380
|
+
width: Math.round(newDisplayWidth),
|
|
381
|
+
widthType: 'pixel'
|
|
382
|
+
}));
|
|
383
|
+
|
|
384
|
+
// Re-create the NodeSelection so the floating toolbar picks up
|
|
385
|
+
// the updated node and renders the full set of controls.
|
|
386
|
+
if (state.selection instanceof _state.NodeSelection) {
|
|
387
|
+
tr.setSelection(_state.NodeSelection.create(tr.doc, mediaSinglePos));
|
|
388
|
+
}
|
|
389
|
+
tr.setMeta('scrollIntoView', false);
|
|
390
|
+
view.dispatch(tr);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Normal (non-replace) path: use the existing batched update mechanism
|
|
396
|
+
(0, _batchMediaNodeAttrs.batchMediaNodeAttrsUpdate)(view, {
|
|
328
397
|
id: dimensions.id,
|
|
329
398
|
nextAttributes: {
|
|
330
399
|
height: dimensions.height,
|
|
@@ -151,7 +151,8 @@ var useMediaAsyncOperations = function useMediaAsyncOperations(_ref3) {
|
|
|
151
151
|
var mediaNode = _ref3.mediaNode,
|
|
152
152
|
mediaNodeUpdater = _ref3.mediaNodeUpdater,
|
|
153
153
|
addPendingTask = _ref3.addPendingTask,
|
|
154
|
-
getPos = _ref3.getPos
|
|
154
|
+
getPos = _ref3.getPos,
|
|
155
|
+
mediaChildNodeId = _ref3.mediaChildNodeId;
|
|
155
156
|
_react.default.useEffect(function () {
|
|
156
157
|
if (!mediaNodeUpdater) {
|
|
157
158
|
return;
|
|
@@ -168,7 +169,11 @@ var useMediaAsyncOperations = function useMediaAsyncOperations(_ref3) {
|
|
|
168
169
|
mediaNode: mediaNode,
|
|
169
170
|
addPendingTask: addPendingTask
|
|
170
171
|
});
|
|
171
|
-
|
|
172
|
+
// mediaChildNodeId is included so this effect re-runs when the media source
|
|
173
|
+
// is replaced (id changes), ensuring getRemoteDimensions fires for the new file
|
|
174
|
+
// with up-to-date updater props after setProps has been called.
|
|
175
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
176
|
+
}, [mediaNode, addPendingTask, mediaNodeUpdater, getPos, mediaChildNodeId]);
|
|
172
177
|
};
|
|
173
178
|
var noop = function noop() {};
|
|
174
179
|
|
|
@@ -287,7 +292,7 @@ var useUpdateSizeCallback = function useUpdateSizeCallback(_ref5) {
|
|
|
287
292
|
*/
|
|
288
293
|
var FALLBACK_MOST_COMMON_WIDTH = 760;
|
|
289
294
|
var MediaSingleNodeNext = exports.MediaSingleNodeNext = function MediaSingleNodeNext(mediaSingleNodeNextProps) {
|
|
290
|
-
var _pluginInjectionApi$m, _mediaNode$
|
|
295
|
+
var _mediaNode$firstChild, _pluginInjectionApi$m, _mediaNode$firstChild2;
|
|
291
296
|
var selected = mediaSingleNodeNextProps.selected,
|
|
292
297
|
getPos = mediaSingleNodeNextProps.getPos,
|
|
293
298
|
nextMediaNode = mediaSingleNodeNextProps.node,
|
|
@@ -334,7 +339,8 @@ var MediaSingleNodeNext = exports.MediaSingleNodeNext = function MediaSingleNode
|
|
|
334
339
|
mediaNodeUpdater: mediaNodeUpdater,
|
|
335
340
|
getPos: getPos,
|
|
336
341
|
mediaNode: mediaNode,
|
|
337
|
-
addPendingTask: addPendingTask || noop
|
|
342
|
+
addPendingTask: addPendingTask || noop,
|
|
343
|
+
mediaChildNodeId: (_mediaNode$firstChild = mediaNode.firstChild) === null || _mediaNode$firstChild === void 0 ? void 0 : _mediaNode$firstChild.attrs.id
|
|
338
344
|
});
|
|
339
345
|
_react.default.useLayoutEffect(function () {
|
|
340
346
|
mountedRef.current = true;
|
|
@@ -429,7 +435,7 @@ var MediaSingleNodeNext = exports.MediaSingleNodeNext = function MediaSingleNode
|
|
|
429
435
|
}, [mediaSingleWidthAttribute, widthType, width, layout, contentWidthForLegacyExperience, containerWidth]);
|
|
430
436
|
var currentMaxWidth = isSelected ? pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$m = pluginInjectionApi.media) === null || _pluginInjectionApi$m === void 0 || (_pluginInjectionApi$m = _pluginInjectionApi$m.sharedState.currentState()) === null || _pluginInjectionApi$m === void 0 ? void 0 : _pluginInjectionApi$m.currentMaxWidth : undefined;
|
|
431
437
|
var contentWidth = currentMaxWidth || lineLength;
|
|
432
|
-
var isCurrentNodeDrafting = Boolean(isDrafting && targetNodeId === (mediaNode === null || mediaNode === void 0 || (_mediaNode$
|
|
438
|
+
var isCurrentNodeDrafting = Boolean(isDrafting && targetNodeId === (mediaNode === null || mediaNode === void 0 || (_mediaNode$firstChild2 = mediaNode.firstChild) === null || _mediaNode$firstChild2 === void 0 ? void 0 : _mediaNode$firstChild2.attrs.id));
|
|
433
439
|
var mediaSingleWrapperRef = /*#__PURE__*/_react.default.createRef();
|
|
434
440
|
var captionPlaceHolderRef = /*#__PURE__*/_react.default.createRef();
|
|
435
441
|
var browser = (0, _browser.getBrowserInfo)();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.computeReplacementDisplayWidth = void 0;
|
|
7
|
+
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
|
|
8
|
+
var MIN_MEDIA_DISPLAY_WIDTH = 24;
|
|
9
|
+
/**
|
|
10
|
+
* Computes the new mediaSingle display width that preserves the original display height
|
|
11
|
+
* when a media node is replaced with a file of a different aspect ratio, clamped to valid bounds.
|
|
12
|
+
*
|
|
13
|
+
* @param targetDisplayHeight - The display height to preserve (from the old image)
|
|
14
|
+
* @param newIntrinsicWidth - The new file's intrinsic pixel width
|
|
15
|
+
* @param newIntrinsicHeight - The new file's intrinsic pixel height
|
|
16
|
+
* @param layout - The mediaSingle layout (affects max width)
|
|
17
|
+
* @param lineLength - The editor content column width in pixels
|
|
18
|
+
*/
|
|
19
|
+
var computeReplacementDisplayWidth = exports.computeReplacementDisplayWidth = function computeReplacementDisplayWidth(targetDisplayHeight, newIntrinsicWidth, newIntrinsicHeight, layout, lineLength) {
|
|
20
|
+
if (newIntrinsicHeight <= 0) {
|
|
21
|
+
return MIN_MEDIA_DISPLAY_WIDTH;
|
|
22
|
+
}
|
|
23
|
+
var unclamped = targetDisplayHeight * (newIntrinsicWidth / newIntrinsicHeight);
|
|
24
|
+
var maxWidth = layout === 'full-width' ? _editorSharedStyles.akEditorFullWidthLayoutWidth : layout === 'wide' ? _editorSharedStyles.akEditorWideLayoutWidth : lineLength;
|
|
25
|
+
return Math.max(MIN_MEDIA_DISPLAY_WIDTH, Math.min(unclamped, maxWidth));
|
|
26
|
+
};
|
|
@@ -15,6 +15,7 @@ var _assert = _interopRequireDefault(require("assert"));
|
|
|
15
15
|
var _react = _interopRequireDefault(require("react"));
|
|
16
16
|
var _reactIntl = require("react-intl");
|
|
17
17
|
var _uuid = _interopRequireDefault(require("uuid"));
|
|
18
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
18
19
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
19
20
|
var _browser = require("@atlaskit/editor-common/browser");
|
|
20
21
|
var _mediaInline = require("@atlaskit/editor-common/media-inline");
|
|
@@ -24,11 +25,12 @@ var _utils = require("@atlaskit/editor-common/utils");
|
|
|
24
25
|
var _state2 = require("@atlaskit/editor-prosemirror/state");
|
|
25
26
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
26
27
|
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
|
|
27
|
-
var
|
|
28
|
+
var _view3 = require("@atlaskit/editor-prosemirror/view");
|
|
28
29
|
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
|
|
29
30
|
var _mediaClient = require("@atlaskit/media-client");
|
|
30
31
|
var _mediaCommon = require("@atlaskit/media-common");
|
|
31
32
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
33
|
+
var _mediaNodeUpdater = require("../nodeviews/mediaNodeUpdater");
|
|
32
34
|
var _helpers = _interopRequireWildcard(require("../pm-plugins/commands/helpers"));
|
|
33
35
|
var helpers = _helpers;
|
|
34
36
|
var _mediaCommon2 = require("../pm-plugins/utils/media-common");
|
|
@@ -95,6 +97,15 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
95
97
|
(0, _defineProperty2.default)(this, "destroyed", false);
|
|
96
98
|
(0, _defineProperty2.default)(this, "removeOnCloseListener", function () {});
|
|
97
99
|
(0, _defineProperty2.default)(this, "onPopupToggleCallback", function () {});
|
|
100
|
+
// When non-null, holds the file ID of the media node being replaced. Used both as a
|
|
101
|
+
// flag (non-null = replace mode) and as a cross-check to ensure the correct node is
|
|
102
|
+
// updated if the selection moves between the picker opening and the file being picked.
|
|
103
|
+
(0, _defineProperty2.default)(this, "replaceMediaFileId", null);
|
|
104
|
+
// The display height (in pixels) of the mediaSingle being replaced, computed at replace time
|
|
105
|
+
// from its display width and the old media node's intrinsic aspect ratio.
|
|
106
|
+
// Used by the nodeview to recompute display width from the new file's aspect ratio after
|
|
107
|
+
// dimensions are fetched, preserving visual height rather than visual width.
|
|
108
|
+
(0, _defineProperty2.default)(this, "replaceMediaTargetDisplayHeight", null);
|
|
98
109
|
(0, _defineProperty2.default)(this, "identifierCount", new Map());
|
|
99
110
|
// This is to enable mediaShallowCopySope to enable only shallow copying media referenced within the edtior
|
|
100
111
|
// see: trackOutOfScopeIdentifier
|
|
@@ -130,7 +141,7 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
130
141
|
* called when we insert a new file via the picker (connected via pickerfacade)
|
|
131
142
|
*/
|
|
132
143
|
(0, _defineProperty2.default)(this, "insertFile", function (mediaState, onMediaStateChanged, pickerType, insertMediaVia) {
|
|
133
|
-
var _this$pluginInjection, _mediaState$collectio, _this$
|
|
144
|
+
var _this$pluginInjection, _mediaState$collectio, _this$pluginInjection3;
|
|
134
145
|
var state = _this.view.state;
|
|
135
146
|
var editorAnalyticsAPI = (_this$pluginInjection = _this.pluginInjectionApi) === null || _this$pluginInjection === void 0 || (_this$pluginInjection = _this$pluginInjection.analytics) === null || _this$pluginInjection === void 0 ? void 0 : _this$pluginInjection.actions;
|
|
136
147
|
var mediaStateWithContext = _objectSpread(_objectSpread({}, mediaState), {}, {
|
|
@@ -141,6 +152,19 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
141
152
|
return;
|
|
142
153
|
}
|
|
143
154
|
|
|
155
|
+
// If replace mode was set but the selection has moved away from a mediaSingle
|
|
156
|
+
// (e.g. the user cancelled the replace picker and then inserted media elsewhere),
|
|
157
|
+
// clear replace state so this insertion proceeds as a normal insert.
|
|
158
|
+
if (_this.replaceMediaFileId !== null) {
|
|
159
|
+
var _state$selection$node;
|
|
160
|
+
var mediaSingle = state.schema.nodes.mediaSingle;
|
|
161
|
+
var isStillOnTargetMedia = state.selection instanceof _state2.NodeSelection && state.selection.node.type === mediaSingle && ((_state$selection$node = state.selection.node.firstChild) === null || _state$selection$node === void 0 ? void 0 : _state$selection$node.attrs.id) === _this.replaceMediaFileId;
|
|
162
|
+
if (!isStillOnTargetMedia) {
|
|
163
|
+
_this.replaceMediaFileId = null;
|
|
164
|
+
_this.replaceMediaTargetDisplayHeight = null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
144
168
|
// We need to dispatch the change to event dispatcher only for successful files
|
|
145
169
|
if (mediaState.status !== 'error') {
|
|
146
170
|
_this.updateAndDispatch({
|
|
@@ -153,13 +177,124 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
153
177
|
});
|
|
154
178
|
_this.uploadInProgressSubscriptionsNotified = true;
|
|
155
179
|
}
|
|
180
|
+
|
|
181
|
+
// Replace mode: if a media node is being replaced, update its attrs in-place
|
|
182
|
+
// rather than inserting a new node. This preserves layout, width, and caption.
|
|
183
|
+
if (_this.replaceMediaFileId !== null) {
|
|
184
|
+
var _mediaState$fileMimeT, _mediaState$fileName, _mediaState$fileSize;
|
|
185
|
+
// Clear replace mode immediately so subsequent insertions behave normally
|
|
186
|
+
_this.replaceMediaFileId = null;
|
|
187
|
+
var currentState = _this.view.state;
|
|
188
|
+
var mediaSinglePos = currentState.selection.from;
|
|
189
|
+
var mediaPos = mediaSinglePos + 1;
|
|
190
|
+
var mediaNode = currentState.doc.nodeAt(mediaPos);
|
|
191
|
+
if (!mediaNode || mediaNode.type.name !== 'media') {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Build a single transaction that:
|
|
196
|
+
// 1. Updates the media child node attrs (new file identity + cleared dimensions)
|
|
197
|
+
// 2. Re-creates the NodeSelection so the toolbar picks up the fresh node
|
|
198
|
+
var tr = currentState.tr;
|
|
199
|
+
tr.step(new _steps.SetAttrsStep(mediaPos, {
|
|
200
|
+
id: mediaState.id,
|
|
201
|
+
collection: collection,
|
|
202
|
+
type: 'file',
|
|
203
|
+
__fileMimeType: (_mediaState$fileMimeT = mediaState.fileMimeType) !== null && _mediaState$fileMimeT !== void 0 ? _mediaState$fileMimeT : null,
|
|
204
|
+
__fileName: (_mediaState$fileName = mediaState.fileName) !== null && _mediaState$fileName !== void 0 ? _mediaState$fileName : null,
|
|
205
|
+
__fileSize: (_mediaState$fileSize = mediaState.fileSize) !== null && _mediaState$fileSize !== void 0 ? _mediaState$fileSize : null,
|
|
206
|
+
__mediaTraceId: null,
|
|
207
|
+
// Clear intrinsic dimensions — they'll be fetched once the file
|
|
208
|
+
// is processed and applied via updateDimensions in a single tx
|
|
209
|
+
// with the height-preserving mediaSingle width adjustment.
|
|
210
|
+
width: null,
|
|
211
|
+
height: null
|
|
212
|
+
}));
|
|
213
|
+
// Re-create the selection so the floating toolbar picks up
|
|
214
|
+
// the updated node and renders the full set of controls.
|
|
215
|
+
tr.setSelection(_state2.NodeSelection.create(tr.doc, mediaSinglePos));
|
|
216
|
+
tr.setMeta('scrollIntoView', false);
|
|
217
|
+
_this.view.dispatch(tr);
|
|
218
|
+
|
|
219
|
+
// Still register the state-change listener so upload completion is tracked
|
|
220
|
+
onMediaStateChanged(_this.handleMediaState);
|
|
221
|
+
var _isEndState = function _isEndState(state) {
|
|
222
|
+
return state.status && MEDIA_RESOLVED_STATES.includes(state.status);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// After the file finishes uploading/processing, trigger a dimension fetch.
|
|
226
|
+
// getRemoteDimensions may fail if called too early (isImageRepresentationReady
|
|
227
|
+
// returns false while processing), so we wait for the ready state first.
|
|
228
|
+
var triggerDimensionFetch = function triggerDimensionFetch() {
|
|
229
|
+
// Find the media node in the doc by id and create a temporary
|
|
230
|
+
// MediaNodeUpdater to fetch and apply dimensions
|
|
231
|
+
var editorState = _this.view.state;
|
|
232
|
+
var mediaSingleType = editorState.schema.nodes.mediaSingle;
|
|
233
|
+
var mediaChildNode = null;
|
|
234
|
+
editorState.doc.descendants(function (node) {
|
|
235
|
+
if (mediaChildNode) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
if (node.type === mediaSingleType) {
|
|
239
|
+
var child = node.firstChild;
|
|
240
|
+
if (child && child.attrs.id === mediaState.id) {
|
|
241
|
+
mediaChildNode = child;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return true;
|
|
245
|
+
});
|
|
246
|
+
if (mediaChildNode) {
|
|
247
|
+
var _this$pluginInjection2;
|
|
248
|
+
var updater = (0, _mediaNodeUpdater.createMediaNodeUpdater)({
|
|
249
|
+
view: _this.view,
|
|
250
|
+
mediaProvider: _this.mediaProvider ? Promise.resolve(_this.mediaProvider) : undefined,
|
|
251
|
+
contextIdentifierProvider: _this.contextIdentifierProvider ? Promise.resolve(_this.contextIdentifierProvider) : undefined,
|
|
252
|
+
node: mediaChildNode,
|
|
253
|
+
isMediaSingle: true,
|
|
254
|
+
lineLength: (_this$pluginInjection2 = _this.pluginInjectionApi) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.width) === null || _this$pluginInjection2 === void 0 || (_this$pluginInjection2 = _this$pluginInjection2.sharedState.currentState()) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.lineLength
|
|
255
|
+
});
|
|
256
|
+
updater.getRemoteDimensions().then(function (dims) {
|
|
257
|
+
if (dims) {
|
|
258
|
+
updater.updateDimensions(dims);
|
|
259
|
+
}
|
|
260
|
+
}).catch(function () {
|
|
261
|
+
// Silently ignore — if dimensions can't be fetched (e.g. network error),
|
|
262
|
+
// the image will render at its current size without the height-preserving
|
|
263
|
+
// width adjustment. This is an acceptable degraded experience.
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
if (!_isEndState(mediaStateWithContext)) {
|
|
268
|
+
var uploadingPromise = new Promise(function (resolve) {
|
|
269
|
+
onMediaStateChanged(function (newState) {
|
|
270
|
+
if (_isEndState(newState)) {
|
|
271
|
+
resolve(newState);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
_this.taskManager.addPendingTask(uploadingPromise, mediaStateWithContext.id).then(function () {
|
|
276
|
+
_this.updateAndDispatch({
|
|
277
|
+
allUploadsFinished: true
|
|
278
|
+
});
|
|
279
|
+
triggerDimensionFetch();
|
|
280
|
+
});
|
|
281
|
+
} else {
|
|
282
|
+
// File is already in a resolved state — fetch dimensions immediately
|
|
283
|
+
triggerDimensionFetch();
|
|
284
|
+
}
|
|
285
|
+
var _view = _this.view;
|
|
286
|
+
if (!_view.hasFocus()) {
|
|
287
|
+
_view.focus();
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
156
291
|
switch ((0, _mediaInline2.getMediaNodeInsertionType)(state, _this.mediaOptions, mediaStateWithContext.fileMimeType)) {
|
|
157
292
|
case 'inline':
|
|
158
293
|
(0, _mediaFiles.insertMediaInlineNode)(editorAnalyticsAPI)(_this.view, mediaStateWithContext, collection, _this.allowInlineImages, _this.getInputMethod(pickerType), insertMediaVia);
|
|
159
294
|
break;
|
|
160
295
|
case 'block':
|
|
161
296
|
// read width state right before inserting to get up-to-date and define values
|
|
162
|
-
var widthPluginState = (_this$
|
|
297
|
+
var widthPluginState = (_this$pluginInjection3 = _this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 || (_this$pluginInjection3 = _this$pluginInjection3.width) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.sharedState.currentState();
|
|
163
298
|
(0, _mediaSingle2.insertMediaSingleNode)(_this.view, mediaStateWithContext, _this.getInputMethod(pickerType), collection, _this.mediaOptions && _this.mediaOptions.alignLeftOnInsert, widthPluginState, editorAnalyticsAPI, _this.onNodeInserted, insertMediaVia, _this.mediaOptions && _this.mediaOptions.allowPixelResizing);
|
|
164
299
|
break;
|
|
165
300
|
case 'group':
|
|
@@ -175,7 +310,7 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
175
310
|
return state.status && MEDIA_RESOLVED_STATES.indexOf(state.status) !== -1;
|
|
176
311
|
};
|
|
177
312
|
if (!isEndState(mediaStateWithContext)) {
|
|
178
|
-
var
|
|
313
|
+
var _uploadingPromise = new Promise(function (resolve) {
|
|
179
314
|
onMediaStateChanged(function (newState) {
|
|
180
315
|
// When media item reaches its final state, remove listener and resolve
|
|
181
316
|
if (isEndState(newState)) {
|
|
@@ -184,7 +319,7 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
184
319
|
});
|
|
185
320
|
});
|
|
186
321
|
if ((0, _platformFeatureFlags.fg)('platform_editor_media_disable_save_during_upload')) {
|
|
187
|
-
_this.taskManager.addPendingTask(
|
|
322
|
+
_this.taskManager.addPendingTask(_uploadingPromise, mediaStateWithContext.id).then(function () {
|
|
188
323
|
_this.updateAndDispatch({
|
|
189
324
|
allUploadsFinished: true
|
|
190
325
|
});
|
|
@@ -198,7 +333,7 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
198
333
|
});
|
|
199
334
|
});
|
|
200
335
|
} else {
|
|
201
|
-
_this.taskManager.addPendingTask(
|
|
336
|
+
_this.taskManager.addPendingTask(_uploadingPromise, mediaStateWithContext.id).then(function () {
|
|
202
337
|
_this.updateAndDispatch({
|
|
203
338
|
allUploadsFinished: true
|
|
204
339
|
});
|
|
@@ -240,6 +375,64 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
240
375
|
}
|
|
241
376
|
_this.onPopupToggleCallback(true);
|
|
242
377
|
});
|
|
378
|
+
/**
|
|
379
|
+
* Opens the media picker in "replace" mode. The next file selected/uploaded
|
|
380
|
+
* will replace the currently selected mediaSingle node's media child in-place,
|
|
381
|
+
* preserving layout, width, and caption.
|
|
382
|
+
*
|
|
383
|
+
* The display height is computed and stored so that after the new file's intrinsic
|
|
384
|
+
* dimensions are fetched, the mediaSingle display width can be adjusted to maintain
|
|
385
|
+
* visual height stability rather than width stability.
|
|
386
|
+
*/
|
|
387
|
+
(0, _defineProperty2.default)(this, "showMediaPickerForReplace", function () {
|
|
388
|
+
var _this$pluginInjection4, _this$pluginInjection5;
|
|
389
|
+
var state = _this.view.state;
|
|
390
|
+
var mediaSingle = state.schema.nodes.mediaSingle;
|
|
391
|
+
var selection = state.selection;
|
|
392
|
+
|
|
393
|
+
// Only activate replace mode when a mediaSingle is selected
|
|
394
|
+
if (!(selection instanceof _state2.NodeSelection) || selection.node.type !== mediaSingle) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
var mediaSingleNode = selection.node;
|
|
398
|
+
var mediaNode = mediaSingleNode.firstChild;
|
|
399
|
+
if (!mediaNode) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Store the current media node's id so insertFile can identify and replace it
|
|
404
|
+
_this.replaceMediaFileId = mediaNode.attrs.id;
|
|
405
|
+
|
|
406
|
+
// Compute and store the current display height so we can preserve it after
|
|
407
|
+
// the new file's intrinsic dimensions are known.
|
|
408
|
+
// displayHeight = displayWidth * (intrinsicHeight / intrinsicWidth)
|
|
409
|
+
var widthAttr = mediaSingleNode.attrs.width;
|
|
410
|
+
var widthType = mediaSingleNode.attrs.widthType;
|
|
411
|
+
var intrinsicWidth = mediaNode.attrs.width;
|
|
412
|
+
var intrinsicHeight = mediaNode.attrs.height;
|
|
413
|
+
|
|
414
|
+
// Resolve actual pixel display width from mediaSingle attrs.
|
|
415
|
+
var lineLength = (_this$pluginInjection4 = (_this$pluginInjection5 = _this.pluginInjectionApi) === null || _this$pluginInjection5 === void 0 || (_this$pluginInjection5 = _this$pluginInjection5.width) === null || _this$pluginInjection5 === void 0 || (_this$pluginInjection5 = _this$pluginInjection5.sharedState.currentState()) === null || _this$pluginInjection5 === void 0 ? void 0 : _this$pluginInjection5.lineLength) !== null && _this$pluginInjection4 !== void 0 ? _this$pluginInjection4 : 760;
|
|
416
|
+
var displayWidth = null;
|
|
417
|
+
if (widthAttr && widthType === 'pixel') {
|
|
418
|
+
displayWidth = widthAttr;
|
|
419
|
+
} else if (widthAttr) {
|
|
420
|
+
// Default widthType is 'percentage' — convert to pixels
|
|
421
|
+
displayWidth = widthAttr / 100 * lineLength;
|
|
422
|
+
} else if (intrinsicWidth) {
|
|
423
|
+
// No width set at all (never resized) — fall back to intrinsic width
|
|
424
|
+
displayWidth = intrinsicWidth;
|
|
425
|
+
}
|
|
426
|
+
if (displayWidth && intrinsicWidth && intrinsicHeight && intrinsicWidth > 0) {
|
|
427
|
+
_this.replaceMediaTargetDisplayHeight = displayWidth * (intrinsicHeight / intrinsicWidth);
|
|
428
|
+
} else {
|
|
429
|
+
// Can't compute display height — fall back to preserving width
|
|
430
|
+
_this.replaceMediaTargetDisplayHeight = null;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Finally, show the media picker
|
|
434
|
+
_this.showMediaPicker();
|
|
435
|
+
});
|
|
243
436
|
(0, _defineProperty2.default)(this, "setBrowseFn", function (browseFn) {
|
|
244
437
|
_this.openMediaPickerBrowser = browseFn;
|
|
245
438
|
});
|
|
@@ -695,8 +888,8 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
695
888
|
}, {
|
|
696
889
|
key: "contextIdentifierProvider",
|
|
697
890
|
get: function get() {
|
|
698
|
-
var _this$
|
|
699
|
-
return (_this$
|
|
891
|
+
var _this$pluginInjection6;
|
|
892
|
+
return (_this$pluginInjection6 = this.pluginInjectionApi) === null || _this$pluginInjection6 === void 0 || (_this$pluginInjection6 = _this$pluginInjection6.contextIdentifier) === null || _this$pluginInjection6 === void 0 || (_this$pluginInjection6 = _this$pluginInjection6.sharedState.currentState()) === null || _this$pluginInjection6 === void 0 ? void 0 : _this$pluginInjection6.contextIdentifierProvider;
|
|
700
893
|
}
|
|
701
894
|
}, {
|
|
702
895
|
key: "selectLastAddedMediaNode",
|
|
@@ -931,9 +1124,9 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
931
1124
|
return;
|
|
932
1125
|
},
|
|
933
1126
|
key: _pluginKey.stateKey,
|
|
934
|
-
view: function view(
|
|
935
|
-
var pluginState = getMediaPluginState(
|
|
936
|
-
pluginState.setView(
|
|
1127
|
+
view: function view(_view2) {
|
|
1128
|
+
var pluginState = getMediaPluginState(_view2.state);
|
|
1129
|
+
pluginState.setView(_view2);
|
|
937
1130
|
pluginState.updateElement();
|
|
938
1131
|
return {
|
|
939
1132
|
update: function update() {
|
|
@@ -953,7 +1146,7 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
953
1146
|
if (state.selection instanceof _state2.TextSelection || state.selection instanceof _state2.AllSelection || state.selection instanceof _cellSelection.CellSelection) {
|
|
954
1147
|
doc.nodesBetween(state.selection.from, state.selection.to, function (node, pos) {
|
|
955
1148
|
if (node.type === schema.nodes.media) {
|
|
956
|
-
mediaNodes.push(
|
|
1149
|
+
mediaNodes.push(_view3.Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
957
1150
|
type: 'media',
|
|
958
1151
|
selected: true
|
|
959
1152
|
}));
|
|
@@ -968,7 +1161,7 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
968
1161
|
if (node.type === schema.nodes.mediaSingle || node.type === schema.nodes.mediaGroup) {
|
|
969
1162
|
doc.nodesBetween($from.pos, $from.pos + node.nodeSize, function (mediaNode, mediaPos) {
|
|
970
1163
|
if (mediaNode.type === schema.nodes.media) {
|
|
971
|
-
mediaNodes.push(
|
|
1164
|
+
mediaNodes.push(_view3.Decoration.node(mediaPos, mediaPos + mediaNode.nodeSize, {}, {
|
|
972
1165
|
type: 'media',
|
|
973
1166
|
selected: true
|
|
974
1167
|
}));
|
|
@@ -980,30 +1173,30 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
980
1173
|
}
|
|
981
1174
|
var pluginState = getMediaPluginState(state);
|
|
982
1175
|
if (!pluginState.showDropzone) {
|
|
983
|
-
return
|
|
1176
|
+
return _view3.DecorationSet.create(state.doc, mediaNodes);
|
|
984
1177
|
}
|
|
985
1178
|
|
|
986
1179
|
// When a media is already selected
|
|
987
1180
|
if (state.selection instanceof _state2.NodeSelection) {
|
|
988
1181
|
var _node = state.selection.node;
|
|
989
1182
|
if (_node.type === schema.nodes.mediaSingle) {
|
|
990
|
-
var deco =
|
|
1183
|
+
var deco = _view3.Decoration.node(state.selection.from, state.selection.to, {
|
|
991
1184
|
class: 'richMedia-selected'
|
|
992
1185
|
});
|
|
993
|
-
return
|
|
1186
|
+
return _view3.DecorationSet.create(state.doc, [deco].concat(mediaNodes));
|
|
994
1187
|
}
|
|
995
|
-
return
|
|
1188
|
+
return _view3.DecorationSet.create(state.doc, mediaNodes);
|
|
996
1189
|
}
|
|
997
1190
|
var pos = $anchor.pos;
|
|
998
1191
|
if ($anchor.parent.type !== schema.nodes.paragraph && $anchor.parent.type !== schema.nodes.codeBlock) {
|
|
999
1192
|
pos = (0, _transform.insertPoint)(state.doc, pos, schema.nodes.mediaGroup);
|
|
1000
1193
|
}
|
|
1001
1194
|
if (pos === null || pos === undefined) {
|
|
1002
|
-
return
|
|
1195
|
+
return _view3.DecorationSet.create(state.doc, mediaNodes);
|
|
1003
1196
|
}
|
|
1004
1197
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
1005
1198
|
var dropPlaceholderKey = (0, _uuid.default)();
|
|
1006
|
-
var dropPlaceholders = [
|
|
1199
|
+
var dropPlaceholders = [_view3.Decoration.widget(pos, function () {
|
|
1007
1200
|
return createDropPlaceholder(intl, nodeViewPortalProviderAPI, dropPlaceholderKey, mediaOptions && mediaOptions.allowDropzoneDropLine);
|
|
1008
1201
|
}, {
|
|
1009
1202
|
key: 'drop-placeholder',
|
|
@@ -1013,7 +1206,7 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
1013
1206
|
}
|
|
1014
1207
|
}
|
|
1015
1208
|
})].concat(mediaNodes);
|
|
1016
|
-
return
|
|
1209
|
+
return _view3.DecorationSet.create(state.doc, dropPlaceholders);
|
|
1017
1210
|
},
|
|
1018
1211
|
nodeViews: options.nodeViews,
|
|
1019
1212
|
handleTextInput: function handleTextInput(view, from, to, text) {
|
|
@@ -29,6 +29,7 @@ var _imageFullscreen = _interopRequireDefault(require("@atlaskit/icon/core/image
|
|
|
29
29
|
var _imageInline = _interopRequireDefault(require("@atlaskit/icon/core/image-inline"));
|
|
30
30
|
var _maximize = _interopRequireDefault(require("@atlaskit/icon/core/maximize"));
|
|
31
31
|
var _smartLinkCard = _interopRequireDefault(require("@atlaskit/icon/core/smart-link-card"));
|
|
32
|
+
var _upload = _interopRequireDefault(require("@atlaskit/icon/core/upload"));
|
|
32
33
|
var _mediaFilmstrip = require("@atlaskit/media-filmstrip");
|
|
33
34
|
var _mediaUi = require("@atlaskit/media-ui");
|
|
34
35
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
@@ -892,6 +893,7 @@ var floatingToolbar = exports.floatingToolbar = function floatingToolbar(state,
|
|
|
892
893
|
if (!mediaPluginState.isResizing && (0, _toolbarFlagCheck.areToolbarFlagsEnabled)(Boolean(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.toolbar))) {
|
|
893
894
|
var _pluginInjectionApi$a0, _pluginInjectionApi$a1, _pluginInjectionApi$a10;
|
|
894
895
|
(0, _utils2.updateToFullHeightSeparator)(items);
|
|
896
|
+
var showReplaceOption = !isViewOnly && mediaPluginState.allowsUploads && (0, _expValEquals.expValEquals)('platform_editor_inline_media_replacement', 'isEnabled', true) && selectedNodeType === mediaSingle;
|
|
895
897
|
var customOptions = [].concat((0, _toConsumableArray2.default)((0, _linking3.getLinkingDropdownOptions)(state, intl, mediaLinkingState, allowMediaInline && selectedNodeType && selectedNodeType === mediaInline, allowLinking, isViewOnly)), (0, _toConsumableArray2.default)((0, _altText2.getAltTextDropdownOption)(state, intl.formatMessage, allowAltTextOnImages, selectedNodeType, pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a0 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a0 === void 0 ? void 0 : _pluginInjectionApi$a0.actions)), (0, _toConsumableArray2.default)((0, _pixelResizing2.getResizeDropdownOption)(options, state, intl.formatMessage, selectedNodeType)));
|
|
896
898
|
if (customOptions.length) {
|
|
897
899
|
customOptions.push({
|
|
@@ -910,7 +912,17 @@ var floatingToolbar = exports.floatingToolbar = function floatingToolbar(state,
|
|
|
910
912
|
type: 'overflow-dropdown',
|
|
911
913
|
id: 'media',
|
|
912
914
|
testId: overflowDropdwonBtnTriggerTestId,
|
|
913
|
-
options: [].concat((0, _toConsumableArray2.default)(customOptions), [
|
|
915
|
+
options: [].concat((0, _toConsumableArray2.default)(customOptions), (0, _toConsumableArray2.default)(showReplaceOption ? [{
|
|
916
|
+
title: intl.formatMessage(_messages.mediaAndEmbedToolbarMessages.replaceMedia),
|
|
917
|
+
onClick: function onClick() {
|
|
918
|
+
mediaPluginState.showMediaPickerForReplace();
|
|
919
|
+
return true;
|
|
920
|
+
},
|
|
921
|
+
icon: /*#__PURE__*/_react.default.createElement(_upload.default, {
|
|
922
|
+
label: ""
|
|
923
|
+
}),
|
|
924
|
+
testId: 'media-replace-toolbar-button'
|
|
925
|
+
}] : []), [_objectSpread({
|
|
914
926
|
title: intl === null || intl === void 0 ? void 0 : intl.formatMessage(_messages.default.copyToClipboard),
|
|
915
927
|
onClick: function onClick() {
|
|
916
928
|
var _pluginInjectionApi$c4, _pluginInjectionApi$f3;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export const hasPrivateAttrsChanged = (currentAttrs, newAttrs) => {
|
|
2
|
-
return currentAttrs.__fileName !== newAttrs.__fileName || currentAttrs.__fileMimeType !== newAttrs.__fileMimeType || currentAttrs.__fileSize !== newAttrs.__fileSize || currentAttrs.__contextId !== newAttrs.__contextId
|
|
2
|
+
return currentAttrs.__fileName !== newAttrs.__fileName || currentAttrs.__fileMimeType !== newAttrs.__fileMimeType || currentAttrs.__fileSize !== newAttrs.__fileSize || currentAttrs.__contextId !== newAttrs.__contextId ||
|
|
3
|
+
// A changed id means the media source was replaced — always re-initialise
|
|
4
|
+
// the updater so getRemoteDimensions fetches dimensions for the new file.
|
|
5
|
+
// Only check when id is explicitly present on the new attrs (it's Partial).
|
|
6
|
+
'id' in newAttrs && currentAttrs.id !== newAttrs.id;
|
|
3
7
|
};
|