@atlaskit/editor-plugin-media 1.29.7 → 1.29.9
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 +16 -0
- package/dist/cjs/nodeviews/mediaNodeUpdater.js +36 -8
- package/dist/cjs/pm-plugins/main.js +2 -0
- package/dist/cjs/utils/batchMediaNodeAttrs.js +161 -0
- package/dist/cjs/utils/batchSteps.js +36 -0
- package/dist/es2019/nodeviews/mediaNodeUpdater.js +36 -8
- package/dist/es2019/pm-plugins/main.js +2 -0
- package/dist/es2019/utils/batchMediaNodeAttrs.js +149 -0
- package/dist/es2019/utils/batchSteps.js +32 -0
- package/dist/esm/nodeviews/mediaNodeUpdater.js +36 -8
- package/dist/esm/pm-plugins/main.js +2 -0
- package/dist/esm/utils/batchMediaNodeAttrs.js +155 -0
- package/dist/esm/utils/batchSteps.js +30 -0
- package/dist/types/utils/batchMediaNodeAttrs.d.ts +54 -0
- package/dist/types/utils/batchSteps.d.ts +19 -0
- package/dist/types-ts4.5/utils/batchMediaNodeAttrs.d.ts +54 -0
- package/dist/types-ts4.5/utils/batchSteps.d.ts +19 -0
- package/package.json +8 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-media
|
|
2
2
|
|
|
3
|
+
## 1.29.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#135555](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/135555)
|
|
8
|
+
[`b7c55014a5c15`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/b7c55014a5c15) -
|
|
9
|
+
add batch steps for media node attributes update
|
|
10
|
+
|
|
11
|
+
## 1.29.8
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#131403](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/131403)
|
|
16
|
+
[`1ac0252dbed37`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/1ac0252dbed37) -
|
|
17
|
+
[ED-24665] Fire analytics event for media insert via file browser
|
|
18
|
+
|
|
3
19
|
## 1.29.7
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -15,7 +15,9 @@ var _analytics = require("@atlaskit/editor-common/analytics");
|
|
|
15
15
|
var _mediaSingle = require("@atlaskit/editor-common/media-single");
|
|
16
16
|
var _mediaClient = require("@atlaskit/media-client");
|
|
17
17
|
var _mediaClientReact = require("@atlaskit/media-client-react");
|
|
18
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
18
19
|
var _helpers = require("../commands/helpers");
|
|
20
|
+
var _batchMediaNodeAttrs = require("../utils/batchMediaNodeAttrs");
|
|
19
21
|
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; }
|
|
20
22
|
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; }
|
|
21
23
|
var isMediaTypeSupported = function isMediaTypeSupported(type) {
|
|
@@ -46,9 +48,18 @@ var MediaNodeUpdater = exports.MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
46
48
|
return _this.getObjectId();
|
|
47
49
|
case 6:
|
|
48
50
|
objectId = _context.sent;
|
|
49
|
-
(0,
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_media_batch_updates')) {
|
|
52
|
+
(0, _batchMediaNodeAttrs.batchMediaNodeAttrsUpdate)(_this.props.view, {
|
|
53
|
+
id: id,
|
|
54
|
+
nextAttributes: {
|
|
55
|
+
__contextId: objectId
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
(0, _helpers.updateAllMediaNodesAttrs)(id, {
|
|
60
|
+
__contextId: objectId
|
|
61
|
+
})(_this.props.view.state, _this.props.view.dispatch);
|
|
62
|
+
}
|
|
52
63
|
case 8:
|
|
53
64
|
case "end":
|
|
54
65
|
return _context.stop();
|
|
@@ -172,7 +183,14 @@ var MediaNodeUpdater = exports.MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
172
183
|
newAttrs = _context4.sent;
|
|
173
184
|
_ref5 = _this.getAttrs(), id = _ref5.id;
|
|
174
185
|
if (id && newAttrs) {
|
|
175
|
-
(0,
|
|
186
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_media_batch_updates')) {
|
|
187
|
+
(0, _batchMediaNodeAttrs.batchMediaNodeAttrsUpdate)(_this.props.view, {
|
|
188
|
+
id: id,
|
|
189
|
+
nextAttributes: newAttrs
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
(0, _helpers.updateAllMediaNodesAttrs)(id, newAttrs)(_this.props.view.state, _this.props.view.dispatch);
|
|
193
|
+
}
|
|
176
194
|
}
|
|
177
195
|
case 5:
|
|
178
196
|
case "end":
|
|
@@ -304,10 +322,20 @@ var MediaNodeUpdater = exports.MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
304
322
|
return attrs.__contextId || null;
|
|
305
323
|
});
|
|
306
324
|
(0, _defineProperty2.default)(this, "updateDimensions", function (dimensions) {
|
|
307
|
-
(0,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
325
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_media_batch_updates')) {
|
|
326
|
+
(0, _batchMediaNodeAttrs.batchMediaNodeAttrsUpdate)(_this.props.view, {
|
|
327
|
+
id: dimensions.id,
|
|
328
|
+
nextAttributes: {
|
|
329
|
+
height: dimensions.height,
|
|
330
|
+
width: dimensions.width
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
} else {
|
|
334
|
+
(0, _helpers.updateAllMediaNodesAttrs)(dimensions.id, {
|
|
335
|
+
height: dimensions.height,
|
|
336
|
+
width: dimensions.width
|
|
337
|
+
})(_this.props.view.state, _this.props.view.dispatch);
|
|
338
|
+
}
|
|
311
339
|
});
|
|
312
340
|
(0, _defineProperty2.default)(this, "hasDifferentContextId", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8() {
|
|
313
341
|
var nodeContextId, currentContextId;
|
|
@@ -331,6 +331,8 @@ var MediaPluginStateImplementation = exports.MediaPluginStateImplementation = /*
|
|
|
331
331
|
return _analytics.INPUT_METHOD.CLIPBOARD;
|
|
332
332
|
case 'dropzone':
|
|
333
333
|
return _analytics.INPUT_METHOD.DRAG_AND_DROP;
|
|
334
|
+
case 'browser':
|
|
335
|
+
return _analytics.INPUT_METHOD.BROWSER;
|
|
334
336
|
}
|
|
335
337
|
return;
|
|
336
338
|
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.runUpdateDebounced = exports.runUpdate = exports.containsSameAttributes = exports.batchMediaNodeAttrsUpdate = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
10
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
|
+
var _debounce = _interopRequireDefault(require("lodash/debounce"));
|
|
12
|
+
var _memoize = _interopRequireDefault(require("lodash/memoize"));
|
|
13
|
+
var _batchSteps = require("./batchSteps");
|
|
14
|
+
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; }
|
|
15
|
+
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; }
|
|
16
|
+
/**
|
|
17
|
+
* 🧱 Internal: Editor FE Platform
|
|
18
|
+
* Based on https://github.com/lodash/lodash/issues/2403#issuecomment-1706130395
|
|
19
|
+
*
|
|
20
|
+
* Creates a debounced function that delays invoking the provided function until after a specified
|
|
21
|
+
* wait time has elapsed since the last time the debounced function was invoked. Additionally, the
|
|
22
|
+
* debounced function is memoized so that the same function instance is used for each unique set
|
|
23
|
+
* of arguments based on the resolver.
|
|
24
|
+
*
|
|
25
|
+
* This is particularly useful in scenarios where you want to debounce function calls while ensuring
|
|
26
|
+
* that each unique input combination receives its own debounced function instance. It's a combination
|
|
27
|
+
* of lodash's `debounce` and `memoize`.
|
|
28
|
+
*
|
|
29
|
+
* @template T
|
|
30
|
+
* @param {T} func - The function to debounce.
|
|
31
|
+
* @param {number} [wait=0] - The number of milliseconds to delay.
|
|
32
|
+
* @param {Object} [options] - The options object to pass to `debounce`.
|
|
33
|
+
* @param {Function} [resolver] - The function to resolve the cache key for memoization.
|
|
34
|
+
* @returns {Function} A new debounced and memoized function.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const debouncedFunction = memoizeDebounce(myFunction, 300, { leading: true }, myResolver);
|
|
38
|
+
* debouncedFunction(arg1, arg2);
|
|
39
|
+
*/
|
|
40
|
+
function memoizeDebounce(func) {
|
|
41
|
+
var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
42
|
+
var options = arguments.length > 2 ? arguments[2] : undefined;
|
|
43
|
+
var resolver = arguments.length > 3 ? arguments[3] : undefined;
|
|
44
|
+
var mem = (0, _memoize.default)(function () {
|
|
45
|
+
return (0, _debounce.default)(func, wait, options);
|
|
46
|
+
}, resolver);
|
|
47
|
+
return function () {
|
|
48
|
+
return mem.apply(void 0, arguments).apply(void 0, arguments);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
var mediaAttributesCache = new WeakMap();
|
|
52
|
+
var debouncedTime = 500;
|
|
53
|
+
var containsSameAttributes = exports.containsSameAttributes = function containsSameAttributes(a, b) {
|
|
54
|
+
// a contains b, and want to check if attributes in b are same in a
|
|
55
|
+
return Object.entries(b).every(function (_ref) {
|
|
56
|
+
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
|
|
57
|
+
bkey = _ref2[0],
|
|
58
|
+
bValue = _ref2[1];
|
|
59
|
+
if (bkey in a) {
|
|
60
|
+
var aValue = a[bkey];
|
|
61
|
+
// Check if types match before comparing values
|
|
62
|
+
return (0, _typeof2.default)(aValue) === (0, _typeof2.default)(bValue) && aValue === bValue;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Updates media node attributes in the editor view based on the provided cache.
|
|
70
|
+
*
|
|
71
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
72
|
+
* @param {MediaAttributesCache} cache - The cache containing media attributes to be updated.
|
|
73
|
+
*
|
|
74
|
+
* This function performs the following steps:
|
|
75
|
+
* 1. Retrieves the media attributes to update from the cache for the given editor view.
|
|
76
|
+
* 2. Clears the media attributes cache for the editor view.
|
|
77
|
+
* 3. Searches for media nodes in the document and collects their positions and new attributes.
|
|
78
|
+
* 4. If there are any media nodes to update, it applies the updates in a batch.
|
|
79
|
+
*/
|
|
80
|
+
var runUpdate = exports.runUpdate = function runUpdate(editorView, cache) {
|
|
81
|
+
var toUpdateValues = cache.get(editorView) || {};
|
|
82
|
+
// clear the media attributes cache per editor view
|
|
83
|
+
cache.delete(editorView);
|
|
84
|
+
var ids = Object.keys(toUpdateValues);
|
|
85
|
+
var state = editorView.state;
|
|
86
|
+
var mediaSteps = [];
|
|
87
|
+
|
|
88
|
+
// search node positions by id
|
|
89
|
+
state.doc.descendants(function (node, position) {
|
|
90
|
+
if (![node.type.schema.nodes.media, node.type.schema.nodes.mediaInline].includes(node.type)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (!ids.includes(node.attrs.id)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
var attrs = toUpdateValues[node.attrs.id];
|
|
97
|
+
if (containsSameAttributes(node.attrs, attrs)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
mediaSteps.push({
|
|
101
|
+
position: position,
|
|
102
|
+
nodeType: node.type.name,
|
|
103
|
+
attrs: attrs
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
if (mediaSteps.length > 0) {
|
|
107
|
+
(0, _batchSteps.batchStepsUpdate)(editorView, mediaSteps);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates a debounced version of the `runUpdate` function to update media node attributes in the editor view.
|
|
113
|
+
*
|
|
114
|
+
* @constant
|
|
115
|
+
* @type {Function}
|
|
116
|
+
* @param {Function} runUpdate - The function to be debounced.
|
|
117
|
+
* @param {number} debouncedTime - The debounce delay in milliseconds.
|
|
118
|
+
* @param {Object} [options] - The debounce options. Defaults to {leading: false, trailing: true}.
|
|
119
|
+
* @param {Function} keyResolver - A function that returns the key to be used for memoization. In this case, it returns the editor view instance.
|
|
120
|
+
*
|
|
121
|
+
* This function performs the following steps:
|
|
122
|
+
* 1. Debounces the `runUpdate` function with the specified delay and options.
|
|
123
|
+
* 2. Uses the editor view instance as the key for memoization to ensure that updates are applied correctly.
|
|
124
|
+
*/
|
|
125
|
+
var runUpdateDebounced = exports.runUpdateDebounced = memoizeDebounce(runUpdate, debouncedTime,
|
|
126
|
+
/**
|
|
127
|
+
* Use the default debounce options:
|
|
128
|
+
* {leading: false, trailing: true}
|
|
129
|
+
*/
|
|
130
|
+
undefined, function (view) {
|
|
131
|
+
/**
|
|
132
|
+
* EditorView is a singleton.
|
|
133
|
+
* There is only one instance per Editor.
|
|
134
|
+
*/
|
|
135
|
+
return view;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Updates the media node attributes cache for the given editor view and triggers a debounced update.
|
|
140
|
+
*
|
|
141
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
142
|
+
* @param {Props} props - The properties containing the media node ID and the next attributes to be updated.
|
|
143
|
+
*
|
|
144
|
+
* This function performs the following steps:
|
|
145
|
+
* 1. Retrieves the media attributes cache for the given editor view.
|
|
146
|
+
* 2. If no cache exists, initializes a new cache.
|
|
147
|
+
* 3. Updates the cache with the new attributes for the specified media node ID.
|
|
148
|
+
* 4. Sets the updated cache back to the media attributes cache.
|
|
149
|
+
* 5. Triggers a debounced update to apply the changes in the editor view.
|
|
150
|
+
*/
|
|
151
|
+
var batchMediaNodeAttrsUpdate = exports.batchMediaNodeAttrsUpdate = function batchMediaNodeAttrsUpdate(editorView, props) {
|
|
152
|
+
var cachePerView = mediaAttributesCache.get(editorView);
|
|
153
|
+
if (!cachePerView) {
|
|
154
|
+
cachePerView = {
|
|
155
|
+
records: {}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
cachePerView[props.id] = _objectSpread(_objectSpread({}, cachePerView[props.id] || {}), props.nextAttributes);
|
|
159
|
+
mediaAttributesCache.set(editorView, cachePerView);
|
|
160
|
+
runUpdateDebounced(editorView, mediaAttributesCache);
|
|
161
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.batchStepsUpdate = void 0;
|
|
7
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
8
|
+
/**
|
|
9
|
+
* Applies a batch of attribute update steps to media nodes in the editor view.
|
|
10
|
+
*
|
|
11
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
12
|
+
* @param {BatchAttrsStepData[]} steps - An array of steps containing the positions and new attributes for media nodes.
|
|
13
|
+
* @returns {boolean} - Returns false if no steps were applied or if the document remains unchanged after applying the steps.
|
|
14
|
+
*
|
|
15
|
+
* This function performs the following steps:
|
|
16
|
+
* 1. Creates a new transaction from the current editor state.
|
|
17
|
+
* 2. If there are no steps to apply, it returns false.
|
|
18
|
+
* 3. Adds a new `BatchAttrsStep` to the transaction with the provided steps.
|
|
19
|
+
* 4. If the transaction has no steps or the document remains unchanged, it returns false.
|
|
20
|
+
* 5. Dispatches the transaction to apply the updates to the editor view.
|
|
21
|
+
*
|
|
22
|
+
* TODO: use pluginInjectionAPI to batch updates from a command in a separate PR later
|
|
23
|
+
*/
|
|
24
|
+
var batchStepsUpdate = exports.batchStepsUpdate = function batchStepsUpdate(editorView, steps) {
|
|
25
|
+
var state = editorView.state,
|
|
26
|
+
dispatch = editorView.dispatch;
|
|
27
|
+
var tr = state.tr;
|
|
28
|
+
if (steps.length === 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
tr.step(new _steps.BatchAttrsStep(steps));
|
|
32
|
+
if (tr.steps.length > 0 && tr.doc.eq(state.doc)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
dispatch(tr);
|
|
36
|
+
};
|
|
@@ -4,7 +4,9 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
|
|
|
4
4
|
import { DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH } from '@atlaskit/editor-common/media-single';
|
|
5
5
|
import { getAttrsFromUrl, isImageRepresentationReady, isMediaBlobUrl } from '@atlaskit/media-client';
|
|
6
6
|
import { getMediaClient } from '@atlaskit/media-client-react';
|
|
7
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
8
|
import { replaceExternalMedia, updateAllMediaNodesAttrs, updateCurrentMediaNodeAttrs, updateMediaNodeAttrs } from '../commands/helpers';
|
|
9
|
+
import { batchMediaNodeAttrsUpdate } from '../utils/batchMediaNodeAttrs';
|
|
8
10
|
const isMediaTypeSupported = type => {
|
|
9
11
|
if (type) {
|
|
10
12
|
return ['image', 'file'].includes(type);
|
|
@@ -23,9 +25,18 @@ export class MediaNodeUpdater {
|
|
|
23
25
|
id
|
|
24
26
|
} = attrs;
|
|
25
27
|
const objectId = await this.getObjectId();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
29
|
+
batchMediaNodeAttrsUpdate(this.props.view, {
|
|
30
|
+
id: id,
|
|
31
|
+
nextAttributes: {
|
|
32
|
+
__contextId: objectId
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
} else {
|
|
36
|
+
updateAllMediaNodesAttrs(id, {
|
|
37
|
+
__contextId: objectId
|
|
38
|
+
})(this.props.view.state, this.props.view.dispatch);
|
|
39
|
+
}
|
|
29
40
|
});
|
|
30
41
|
_defineProperty(this, "updateNodeContextId", async getPos => {
|
|
31
42
|
const attrs = this.getAttrs();
|
|
@@ -89,7 +100,14 @@ export class MediaNodeUpdater {
|
|
|
89
100
|
id
|
|
90
101
|
} = this.getAttrs();
|
|
91
102
|
if (id && newAttrs) {
|
|
92
|
-
|
|
103
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
104
|
+
batchMediaNodeAttrsUpdate(this.props.view, {
|
|
105
|
+
id: id,
|
|
106
|
+
nextAttributes: newAttrs
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
updateAllMediaNodesAttrs(id, newAttrs)(this.props.view.state, this.props.view.dispatch);
|
|
110
|
+
}
|
|
93
111
|
}
|
|
94
112
|
});
|
|
95
113
|
_defineProperty(this, "updateNodeAttrs", async getPos => {
|
|
@@ -163,10 +181,20 @@ export class MediaNodeUpdater {
|
|
|
163
181
|
return attrs.__contextId || null;
|
|
164
182
|
});
|
|
165
183
|
_defineProperty(this, "updateDimensions", dimensions => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
184
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
185
|
+
batchMediaNodeAttrsUpdate(this.props.view, {
|
|
186
|
+
id: dimensions.id,
|
|
187
|
+
nextAttributes: {
|
|
188
|
+
height: dimensions.height,
|
|
189
|
+
width: dimensions.width
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
updateAllMediaNodesAttrs(dimensions.id, {
|
|
194
|
+
height: dimensions.height,
|
|
195
|
+
width: dimensions.width
|
|
196
|
+
})(this.props.view.state, this.props.view.dispatch);
|
|
197
|
+
}
|
|
170
198
|
});
|
|
171
199
|
_defineProperty(this, "hasDifferentContextId", async () => {
|
|
172
200
|
const nodeContextId = this.getNodeContextId();
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import debounce from 'lodash/debounce';
|
|
2
|
+
import memoize from 'lodash/memoize';
|
|
3
|
+
import { batchStepsUpdate } from './batchSteps';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 🧱 Internal: Editor FE Platform
|
|
7
|
+
* Based on https://github.com/lodash/lodash/issues/2403#issuecomment-1706130395
|
|
8
|
+
*
|
|
9
|
+
* Creates a debounced function that delays invoking the provided function until after a specified
|
|
10
|
+
* wait time has elapsed since the last time the debounced function was invoked. Additionally, the
|
|
11
|
+
* debounced function is memoized so that the same function instance is used for each unique set
|
|
12
|
+
* of arguments based on the resolver.
|
|
13
|
+
*
|
|
14
|
+
* This is particularly useful in scenarios where you want to debounce function calls while ensuring
|
|
15
|
+
* that each unique input combination receives its own debounced function instance. It's a combination
|
|
16
|
+
* of lodash's `debounce` and `memoize`.
|
|
17
|
+
*
|
|
18
|
+
* @template T
|
|
19
|
+
* @param {T} func - The function to debounce.
|
|
20
|
+
* @param {number} [wait=0] - The number of milliseconds to delay.
|
|
21
|
+
* @param {Object} [options] - The options object to pass to `debounce`.
|
|
22
|
+
* @param {Function} [resolver] - The function to resolve the cache key for memoization.
|
|
23
|
+
* @returns {Function} A new debounced and memoized function.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const debouncedFunction = memoizeDebounce(myFunction, 300, { leading: true }, myResolver);
|
|
27
|
+
* debouncedFunction(arg1, arg2);
|
|
28
|
+
*/
|
|
29
|
+
function memoizeDebounce(func, wait = 0, options, resolver) {
|
|
30
|
+
const mem = memoize(function () {
|
|
31
|
+
return debounce(func, wait, options);
|
|
32
|
+
}, resolver);
|
|
33
|
+
return function (...args) {
|
|
34
|
+
return mem(...args)(...args);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const mediaAttributesCache = new WeakMap();
|
|
38
|
+
const debouncedTime = 500;
|
|
39
|
+
export const containsSameAttributes = (a, b) => {
|
|
40
|
+
// a contains b, and want to check if attributes in b are same in a
|
|
41
|
+
return Object.entries(b).every(([bkey, bValue]) => {
|
|
42
|
+
if (bkey in a) {
|
|
43
|
+
const aValue = a[bkey];
|
|
44
|
+
// Check if types match before comparing values
|
|
45
|
+
return typeof aValue === typeof bValue && aValue === bValue;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Updates media node attributes in the editor view based on the provided cache.
|
|
53
|
+
*
|
|
54
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
55
|
+
* @param {MediaAttributesCache} cache - The cache containing media attributes to be updated.
|
|
56
|
+
*
|
|
57
|
+
* This function performs the following steps:
|
|
58
|
+
* 1. Retrieves the media attributes to update from the cache for the given editor view.
|
|
59
|
+
* 2. Clears the media attributes cache for the editor view.
|
|
60
|
+
* 3. Searches for media nodes in the document and collects their positions and new attributes.
|
|
61
|
+
* 4. If there are any media nodes to update, it applies the updates in a batch.
|
|
62
|
+
*/
|
|
63
|
+
export const runUpdate = (editorView, cache) => {
|
|
64
|
+
const toUpdateValues = cache.get(editorView) || {};
|
|
65
|
+
// clear the media attributes cache per editor view
|
|
66
|
+
cache.delete(editorView);
|
|
67
|
+
const ids = Object.keys(toUpdateValues);
|
|
68
|
+
const {
|
|
69
|
+
state
|
|
70
|
+
} = editorView;
|
|
71
|
+
const mediaSteps = [];
|
|
72
|
+
|
|
73
|
+
// search node positions by id
|
|
74
|
+
state.doc.descendants((node, position) => {
|
|
75
|
+
if (![node.type.schema.nodes.media, node.type.schema.nodes.mediaInline].includes(node.type)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (!ids.includes(node.attrs.id)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
const attrs = toUpdateValues[node.attrs.id];
|
|
82
|
+
if (containsSameAttributes(node.attrs, attrs)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
mediaSteps.push({
|
|
86
|
+
position,
|
|
87
|
+
nodeType: node.type.name,
|
|
88
|
+
attrs
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
if (mediaSteps.length > 0) {
|
|
92
|
+
batchStepsUpdate(editorView, mediaSteps);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Creates a debounced version of the `runUpdate` function to update media node attributes in the editor view.
|
|
98
|
+
*
|
|
99
|
+
* @constant
|
|
100
|
+
* @type {Function}
|
|
101
|
+
* @param {Function} runUpdate - The function to be debounced.
|
|
102
|
+
* @param {number} debouncedTime - The debounce delay in milliseconds.
|
|
103
|
+
* @param {Object} [options] - The debounce options. Defaults to {leading: false, trailing: true}.
|
|
104
|
+
* @param {Function} keyResolver - A function that returns the key to be used for memoization. In this case, it returns the editor view instance.
|
|
105
|
+
*
|
|
106
|
+
* This function performs the following steps:
|
|
107
|
+
* 1. Debounces the `runUpdate` function with the specified delay and options.
|
|
108
|
+
* 2. Uses the editor view instance as the key for memoization to ensure that updates are applied correctly.
|
|
109
|
+
*/
|
|
110
|
+
export const runUpdateDebounced = memoizeDebounce(runUpdate, debouncedTime,
|
|
111
|
+
/**
|
|
112
|
+
* Use the default debounce options:
|
|
113
|
+
* {leading: false, trailing: true}
|
|
114
|
+
*/
|
|
115
|
+
undefined, view => {
|
|
116
|
+
/**
|
|
117
|
+
* EditorView is a singleton.
|
|
118
|
+
* There is only one instance per Editor.
|
|
119
|
+
*/
|
|
120
|
+
return view;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Updates the media node attributes cache for the given editor view and triggers a debounced update.
|
|
125
|
+
*
|
|
126
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
127
|
+
* @param {Props} props - The properties containing the media node ID and the next attributes to be updated.
|
|
128
|
+
*
|
|
129
|
+
* This function performs the following steps:
|
|
130
|
+
* 1. Retrieves the media attributes cache for the given editor view.
|
|
131
|
+
* 2. If no cache exists, initializes a new cache.
|
|
132
|
+
* 3. Updates the cache with the new attributes for the specified media node ID.
|
|
133
|
+
* 4. Sets the updated cache back to the media attributes cache.
|
|
134
|
+
* 5. Triggers a debounced update to apply the changes in the editor view.
|
|
135
|
+
*/
|
|
136
|
+
export const batchMediaNodeAttrsUpdate = (editorView, props) => {
|
|
137
|
+
let cachePerView = mediaAttributesCache.get(editorView);
|
|
138
|
+
if (!cachePerView) {
|
|
139
|
+
cachePerView = {
|
|
140
|
+
records: {}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
cachePerView[props.id] = {
|
|
144
|
+
...(cachePerView[props.id] || {}),
|
|
145
|
+
...props.nextAttributes
|
|
146
|
+
};
|
|
147
|
+
mediaAttributesCache.set(editorView, cachePerView);
|
|
148
|
+
runUpdateDebounced(editorView, mediaAttributesCache);
|
|
149
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BatchAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a batch of attribute update steps to media nodes in the editor view.
|
|
4
|
+
*
|
|
5
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
6
|
+
* @param {BatchAttrsStepData[]} steps - An array of steps containing the positions and new attributes for media nodes.
|
|
7
|
+
* @returns {boolean} - Returns false if no steps were applied or if the document remains unchanged after applying the steps.
|
|
8
|
+
*
|
|
9
|
+
* This function performs the following steps:
|
|
10
|
+
* 1. Creates a new transaction from the current editor state.
|
|
11
|
+
* 2. If there are no steps to apply, it returns false.
|
|
12
|
+
* 3. Adds a new `BatchAttrsStep` to the transaction with the provided steps.
|
|
13
|
+
* 4. If the transaction has no steps or the document remains unchanged, it returns false.
|
|
14
|
+
* 5. Dispatches the transaction to apply the updates to the editor view.
|
|
15
|
+
*
|
|
16
|
+
* TODO: use pluginInjectionAPI to batch updates from a command in a separate PR later
|
|
17
|
+
*/
|
|
18
|
+
export const batchStepsUpdate = (editorView, steps) => {
|
|
19
|
+
const {
|
|
20
|
+
state,
|
|
21
|
+
dispatch
|
|
22
|
+
} = editorView;
|
|
23
|
+
const tr = state.tr;
|
|
24
|
+
if (steps.length === 0) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
tr.step(new BatchAttrsStep(steps));
|
|
28
|
+
if (tr.steps.length > 0 && tr.doc.eq(state.doc)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
dispatch(tr);
|
|
32
|
+
};
|
|
@@ -10,7 +10,9 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
|
|
|
10
10
|
import { DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH } from '@atlaskit/editor-common/media-single';
|
|
11
11
|
import { getAttrsFromUrl, isImageRepresentationReady, isMediaBlobUrl as _isMediaBlobUrl } from '@atlaskit/media-client';
|
|
12
12
|
import { getMediaClient } from '@atlaskit/media-client-react';
|
|
13
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
14
|
import { replaceExternalMedia, updateAllMediaNodesAttrs, updateCurrentMediaNodeAttrs, updateMediaNodeAttrs } from '../commands/helpers';
|
|
15
|
+
import { batchMediaNodeAttrsUpdate } from '../utils/batchMediaNodeAttrs';
|
|
14
16
|
var isMediaTypeSupported = function isMediaTypeSupported(type) {
|
|
15
17
|
if (type) {
|
|
16
18
|
return ['image', 'file'].includes(type);
|
|
@@ -39,9 +41,18 @@ export var MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
39
41
|
return _this.getObjectId();
|
|
40
42
|
case 6:
|
|
41
43
|
objectId = _context.sent;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
45
|
+
batchMediaNodeAttrsUpdate(_this.props.view, {
|
|
46
|
+
id: id,
|
|
47
|
+
nextAttributes: {
|
|
48
|
+
__contextId: objectId
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
} else {
|
|
52
|
+
updateAllMediaNodesAttrs(id, {
|
|
53
|
+
__contextId: objectId
|
|
54
|
+
})(_this.props.view.state, _this.props.view.dispatch);
|
|
55
|
+
}
|
|
45
56
|
case 8:
|
|
46
57
|
case "end":
|
|
47
58
|
return _context.stop();
|
|
@@ -165,7 +176,14 @@ export var MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
165
176
|
newAttrs = _context4.sent;
|
|
166
177
|
_ref5 = _this.getAttrs(), id = _ref5.id;
|
|
167
178
|
if (id && newAttrs) {
|
|
168
|
-
|
|
179
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
180
|
+
batchMediaNodeAttrsUpdate(_this.props.view, {
|
|
181
|
+
id: id,
|
|
182
|
+
nextAttributes: newAttrs
|
|
183
|
+
});
|
|
184
|
+
} else {
|
|
185
|
+
updateAllMediaNodesAttrs(id, newAttrs)(_this.props.view.state, _this.props.view.dispatch);
|
|
186
|
+
}
|
|
169
187
|
}
|
|
170
188
|
case 5:
|
|
171
189
|
case "end":
|
|
@@ -297,10 +315,20 @@ export var MediaNodeUpdater = /*#__PURE__*/function () {
|
|
|
297
315
|
return attrs.__contextId || null;
|
|
298
316
|
});
|
|
299
317
|
_defineProperty(this, "updateDimensions", function (dimensions) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
318
|
+
if (fg('platform_editor_media_batch_updates')) {
|
|
319
|
+
batchMediaNodeAttrsUpdate(_this.props.view, {
|
|
320
|
+
id: dimensions.id,
|
|
321
|
+
nextAttributes: {
|
|
322
|
+
height: dimensions.height,
|
|
323
|
+
width: dimensions.width
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
} else {
|
|
327
|
+
updateAllMediaNodesAttrs(dimensions.id, {
|
|
328
|
+
height: dimensions.height,
|
|
329
|
+
width: dimensions.width
|
|
330
|
+
})(_this.props.view.state, _this.props.view.dispatch);
|
|
331
|
+
}
|
|
304
332
|
});
|
|
305
333
|
_defineProperty(this, "hasDifferentContextId", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
|
|
306
334
|
var nodeContextId, currentContextId;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _typeof from "@babel/runtime/helpers/typeof";
|
|
3
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
|
+
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; }
|
|
5
|
+
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; }
|
|
6
|
+
import debounce from 'lodash/debounce';
|
|
7
|
+
import memoize from 'lodash/memoize';
|
|
8
|
+
import { batchStepsUpdate } from './batchSteps';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 🧱 Internal: Editor FE Platform
|
|
12
|
+
* Based on https://github.com/lodash/lodash/issues/2403#issuecomment-1706130395
|
|
13
|
+
*
|
|
14
|
+
* Creates a debounced function that delays invoking the provided function until after a specified
|
|
15
|
+
* wait time has elapsed since the last time the debounced function was invoked. Additionally, the
|
|
16
|
+
* debounced function is memoized so that the same function instance is used for each unique set
|
|
17
|
+
* of arguments based on the resolver.
|
|
18
|
+
*
|
|
19
|
+
* This is particularly useful in scenarios where you want to debounce function calls while ensuring
|
|
20
|
+
* that each unique input combination receives its own debounced function instance. It's a combination
|
|
21
|
+
* of lodash's `debounce` and `memoize`.
|
|
22
|
+
*
|
|
23
|
+
* @template T
|
|
24
|
+
* @param {T} func - The function to debounce.
|
|
25
|
+
* @param {number} [wait=0] - The number of milliseconds to delay.
|
|
26
|
+
* @param {Object} [options] - The options object to pass to `debounce`.
|
|
27
|
+
* @param {Function} [resolver] - The function to resolve the cache key for memoization.
|
|
28
|
+
* @returns {Function} A new debounced and memoized function.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const debouncedFunction = memoizeDebounce(myFunction, 300, { leading: true }, myResolver);
|
|
32
|
+
* debouncedFunction(arg1, arg2);
|
|
33
|
+
*/
|
|
34
|
+
function memoizeDebounce(func) {
|
|
35
|
+
var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
36
|
+
var options = arguments.length > 2 ? arguments[2] : undefined;
|
|
37
|
+
var resolver = arguments.length > 3 ? arguments[3] : undefined;
|
|
38
|
+
var mem = memoize(function () {
|
|
39
|
+
return debounce(func, wait, options);
|
|
40
|
+
}, resolver);
|
|
41
|
+
return function () {
|
|
42
|
+
return mem.apply(void 0, arguments).apply(void 0, arguments);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
var mediaAttributesCache = new WeakMap();
|
|
46
|
+
var debouncedTime = 500;
|
|
47
|
+
export var containsSameAttributes = function containsSameAttributes(a, b) {
|
|
48
|
+
// a contains b, and want to check if attributes in b are same in a
|
|
49
|
+
return Object.entries(b).every(function (_ref) {
|
|
50
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
51
|
+
bkey = _ref2[0],
|
|
52
|
+
bValue = _ref2[1];
|
|
53
|
+
if (bkey in a) {
|
|
54
|
+
var aValue = a[bkey];
|
|
55
|
+
// Check if types match before comparing values
|
|
56
|
+
return _typeof(aValue) === _typeof(bValue) && aValue === bValue;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Updates media node attributes in the editor view based on the provided cache.
|
|
64
|
+
*
|
|
65
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
66
|
+
* @param {MediaAttributesCache} cache - The cache containing media attributes to be updated.
|
|
67
|
+
*
|
|
68
|
+
* This function performs the following steps:
|
|
69
|
+
* 1. Retrieves the media attributes to update from the cache for the given editor view.
|
|
70
|
+
* 2. Clears the media attributes cache for the editor view.
|
|
71
|
+
* 3. Searches for media nodes in the document and collects their positions and new attributes.
|
|
72
|
+
* 4. If there are any media nodes to update, it applies the updates in a batch.
|
|
73
|
+
*/
|
|
74
|
+
export var runUpdate = function runUpdate(editorView, cache) {
|
|
75
|
+
var toUpdateValues = cache.get(editorView) || {};
|
|
76
|
+
// clear the media attributes cache per editor view
|
|
77
|
+
cache.delete(editorView);
|
|
78
|
+
var ids = Object.keys(toUpdateValues);
|
|
79
|
+
var state = editorView.state;
|
|
80
|
+
var mediaSteps = [];
|
|
81
|
+
|
|
82
|
+
// search node positions by id
|
|
83
|
+
state.doc.descendants(function (node, position) {
|
|
84
|
+
if (![node.type.schema.nodes.media, node.type.schema.nodes.mediaInline].includes(node.type)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (!ids.includes(node.attrs.id)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
var attrs = toUpdateValues[node.attrs.id];
|
|
91
|
+
if (containsSameAttributes(node.attrs, attrs)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
mediaSteps.push({
|
|
95
|
+
position: position,
|
|
96
|
+
nodeType: node.type.name,
|
|
97
|
+
attrs: attrs
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
if (mediaSteps.length > 0) {
|
|
101
|
+
batchStepsUpdate(editorView, mediaSteps);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Creates a debounced version of the `runUpdate` function to update media node attributes in the editor view.
|
|
107
|
+
*
|
|
108
|
+
* @constant
|
|
109
|
+
* @type {Function}
|
|
110
|
+
* @param {Function} runUpdate - The function to be debounced.
|
|
111
|
+
* @param {number} debouncedTime - The debounce delay in milliseconds.
|
|
112
|
+
* @param {Object} [options] - The debounce options. Defaults to {leading: false, trailing: true}.
|
|
113
|
+
* @param {Function} keyResolver - A function that returns the key to be used for memoization. In this case, it returns the editor view instance.
|
|
114
|
+
*
|
|
115
|
+
* This function performs the following steps:
|
|
116
|
+
* 1. Debounces the `runUpdate` function with the specified delay and options.
|
|
117
|
+
* 2. Uses the editor view instance as the key for memoization to ensure that updates are applied correctly.
|
|
118
|
+
*/
|
|
119
|
+
export var runUpdateDebounced = memoizeDebounce(runUpdate, debouncedTime,
|
|
120
|
+
/**
|
|
121
|
+
* Use the default debounce options:
|
|
122
|
+
* {leading: false, trailing: true}
|
|
123
|
+
*/
|
|
124
|
+
undefined, function (view) {
|
|
125
|
+
/**
|
|
126
|
+
* EditorView is a singleton.
|
|
127
|
+
* There is only one instance per Editor.
|
|
128
|
+
*/
|
|
129
|
+
return view;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Updates the media node attributes cache for the given editor view and triggers a debounced update.
|
|
134
|
+
*
|
|
135
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
136
|
+
* @param {Props} props - The properties containing the media node ID and the next attributes to be updated.
|
|
137
|
+
*
|
|
138
|
+
* This function performs the following steps:
|
|
139
|
+
* 1. Retrieves the media attributes cache for the given editor view.
|
|
140
|
+
* 2. If no cache exists, initializes a new cache.
|
|
141
|
+
* 3. Updates the cache with the new attributes for the specified media node ID.
|
|
142
|
+
* 4. Sets the updated cache back to the media attributes cache.
|
|
143
|
+
* 5. Triggers a debounced update to apply the changes in the editor view.
|
|
144
|
+
*/
|
|
145
|
+
export var batchMediaNodeAttrsUpdate = function batchMediaNodeAttrsUpdate(editorView, props) {
|
|
146
|
+
var cachePerView = mediaAttributesCache.get(editorView);
|
|
147
|
+
if (!cachePerView) {
|
|
148
|
+
cachePerView = {
|
|
149
|
+
records: {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
cachePerView[props.id] = _objectSpread(_objectSpread({}, cachePerView[props.id] || {}), props.nextAttributes);
|
|
153
|
+
mediaAttributesCache.set(editorView, cachePerView);
|
|
154
|
+
runUpdateDebounced(editorView, mediaAttributesCache);
|
|
155
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BatchAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a batch of attribute update steps to media nodes in the editor view.
|
|
4
|
+
*
|
|
5
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
6
|
+
* @param {BatchAttrsStepData[]} steps - An array of steps containing the positions and new attributes for media nodes.
|
|
7
|
+
* @returns {boolean} - Returns false if no steps were applied or if the document remains unchanged after applying the steps.
|
|
8
|
+
*
|
|
9
|
+
* This function performs the following steps:
|
|
10
|
+
* 1. Creates a new transaction from the current editor state.
|
|
11
|
+
* 2. If there are no steps to apply, it returns false.
|
|
12
|
+
* 3. Adds a new `BatchAttrsStep` to the transaction with the provided steps.
|
|
13
|
+
* 4. If the transaction has no steps or the document remains unchanged, it returns false.
|
|
14
|
+
* 5. Dispatches the transaction to apply the updates to the editor view.
|
|
15
|
+
*
|
|
16
|
+
* TODO: use pluginInjectionAPI to batch updates from a command in a separate PR later
|
|
17
|
+
*/
|
|
18
|
+
export var batchStepsUpdate = function batchStepsUpdate(editorView, steps) {
|
|
19
|
+
var state = editorView.state,
|
|
20
|
+
dispatch = editorView.dispatch;
|
|
21
|
+
var tr = state.tr;
|
|
22
|
+
if (steps.length === 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
tr.step(new BatchAttrsStep(steps));
|
|
26
|
+
if (tr.steps.length > 0 && tr.doc.eq(state.doc)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
dispatch(tr);
|
|
30
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type MediaAttributes } from '@atlaskit/adf-schema';
|
|
2
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
type MediaId = string;
|
|
4
|
+
type Props = {
|
|
5
|
+
id: MediaId;
|
|
6
|
+
nextAttributes: Partial<MediaAttributes>;
|
|
7
|
+
};
|
|
8
|
+
export type MediaAttributesMap = Record<MediaId, Partial<MediaAttributes>>;
|
|
9
|
+
type MediaAttributesCachePerView = MediaAttributesMap;
|
|
10
|
+
export type MediaAttributesCache = WeakMap<EditorView, MediaAttributesCachePerView>;
|
|
11
|
+
export declare const containsSameAttributes: (a: MediaAttributes, b: Partial<MediaAttributes>) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Updates media node attributes in the editor view based on the provided cache.
|
|
14
|
+
*
|
|
15
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
16
|
+
* @param {MediaAttributesCache} cache - The cache containing media attributes to be updated.
|
|
17
|
+
*
|
|
18
|
+
* This function performs the following steps:
|
|
19
|
+
* 1. Retrieves the media attributes to update from the cache for the given editor view.
|
|
20
|
+
* 2. Clears the media attributes cache for the editor view.
|
|
21
|
+
* 3. Searches for media nodes in the document and collects their positions and new attributes.
|
|
22
|
+
* 4. If there are any media nodes to update, it applies the updates in a batch.
|
|
23
|
+
*/
|
|
24
|
+
export declare const runUpdate: (editorView: EditorView, cache: MediaAttributesCache) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a debounced version of the `runUpdate` function to update media node attributes in the editor view.
|
|
27
|
+
*
|
|
28
|
+
* @constant
|
|
29
|
+
* @type {Function}
|
|
30
|
+
* @param {Function} runUpdate - The function to be debounced.
|
|
31
|
+
* @param {number} debouncedTime - The debounce delay in milliseconds.
|
|
32
|
+
* @param {Object} [options] - The debounce options. Defaults to {leading: false, trailing: true}.
|
|
33
|
+
* @param {Function} keyResolver - A function that returns the key to be used for memoization. In this case, it returns the editor view instance.
|
|
34
|
+
*
|
|
35
|
+
* This function performs the following steps:
|
|
36
|
+
* 1. Debounces the `runUpdate` function with the specified delay and options.
|
|
37
|
+
* 2. Uses the editor view instance as the key for memoization to ensure that updates are applied correctly.
|
|
38
|
+
*/
|
|
39
|
+
export declare const runUpdateDebounced: (editorView: EditorView, cache: MediaAttributesCache) => void | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Updates the media node attributes cache for the given editor view and triggers a debounced update.
|
|
42
|
+
*
|
|
43
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
44
|
+
* @param {Props} props - The properties containing the media node ID and the next attributes to be updated.
|
|
45
|
+
*
|
|
46
|
+
* This function performs the following steps:
|
|
47
|
+
* 1. Retrieves the media attributes cache for the given editor view.
|
|
48
|
+
* 2. If no cache exists, initializes a new cache.
|
|
49
|
+
* 3. Updates the cache with the new attributes for the specified media node ID.
|
|
50
|
+
* 4. Sets the updated cache back to the media attributes cache.
|
|
51
|
+
* 5. Triggers a debounced update to apply the changes in the editor view.
|
|
52
|
+
*/
|
|
53
|
+
export declare const batchMediaNodeAttrsUpdate: (editorView: EditorView, props: Props) => void;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type BatchAttrsStepData } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
/**
|
|
4
|
+
* Applies a batch of attribute update steps to media nodes in the editor view.
|
|
5
|
+
*
|
|
6
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
7
|
+
* @param {BatchAttrsStepData[]} steps - An array of steps containing the positions and new attributes for media nodes.
|
|
8
|
+
* @returns {boolean} - Returns false if no steps were applied or if the document remains unchanged after applying the steps.
|
|
9
|
+
*
|
|
10
|
+
* This function performs the following steps:
|
|
11
|
+
* 1. Creates a new transaction from the current editor state.
|
|
12
|
+
* 2. If there are no steps to apply, it returns false.
|
|
13
|
+
* 3. Adds a new `BatchAttrsStep` to the transaction with the provided steps.
|
|
14
|
+
* 4. If the transaction has no steps or the document remains unchanged, it returns false.
|
|
15
|
+
* 5. Dispatches the transaction to apply the updates to the editor view.
|
|
16
|
+
*
|
|
17
|
+
* TODO: use pluginInjectionAPI to batch updates from a command in a separate PR later
|
|
18
|
+
*/
|
|
19
|
+
export declare const batchStepsUpdate: (editorView: EditorView, steps: BatchAttrsStepData[]) => false | undefined;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type MediaAttributes } from '@atlaskit/adf-schema';
|
|
2
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
type MediaId = string;
|
|
4
|
+
type Props = {
|
|
5
|
+
id: MediaId;
|
|
6
|
+
nextAttributes: Partial<MediaAttributes>;
|
|
7
|
+
};
|
|
8
|
+
export type MediaAttributesMap = Record<MediaId, Partial<MediaAttributes>>;
|
|
9
|
+
type MediaAttributesCachePerView = MediaAttributesMap;
|
|
10
|
+
export type MediaAttributesCache = WeakMap<EditorView, MediaAttributesCachePerView>;
|
|
11
|
+
export declare const containsSameAttributes: (a: MediaAttributes, b: Partial<MediaAttributes>) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Updates media node attributes in the editor view based on the provided cache.
|
|
14
|
+
*
|
|
15
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
16
|
+
* @param {MediaAttributesCache} cache - The cache containing media attributes to be updated.
|
|
17
|
+
*
|
|
18
|
+
* This function performs the following steps:
|
|
19
|
+
* 1. Retrieves the media attributes to update from the cache for the given editor view.
|
|
20
|
+
* 2. Clears the media attributes cache for the editor view.
|
|
21
|
+
* 3. Searches for media nodes in the document and collects their positions and new attributes.
|
|
22
|
+
* 4. If there are any media nodes to update, it applies the updates in a batch.
|
|
23
|
+
*/
|
|
24
|
+
export declare const runUpdate: (editorView: EditorView, cache: MediaAttributesCache) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a debounced version of the `runUpdate` function to update media node attributes in the editor view.
|
|
27
|
+
*
|
|
28
|
+
* @constant
|
|
29
|
+
* @type {Function}
|
|
30
|
+
* @param {Function} runUpdate - The function to be debounced.
|
|
31
|
+
* @param {number} debouncedTime - The debounce delay in milliseconds.
|
|
32
|
+
* @param {Object} [options] - The debounce options. Defaults to {leading: false, trailing: true}.
|
|
33
|
+
* @param {Function} keyResolver - A function that returns the key to be used for memoization. In this case, it returns the editor view instance.
|
|
34
|
+
*
|
|
35
|
+
* This function performs the following steps:
|
|
36
|
+
* 1. Debounces the `runUpdate` function with the specified delay and options.
|
|
37
|
+
* 2. Uses the editor view instance as the key for memoization to ensure that updates are applied correctly.
|
|
38
|
+
*/
|
|
39
|
+
export declare const runUpdateDebounced: (editorView: EditorView, cache: MediaAttributesCache) => void | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Updates the media node attributes cache for the given editor view and triggers a debounced update.
|
|
42
|
+
*
|
|
43
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
44
|
+
* @param {Props} props - The properties containing the media node ID and the next attributes to be updated.
|
|
45
|
+
*
|
|
46
|
+
* This function performs the following steps:
|
|
47
|
+
* 1. Retrieves the media attributes cache for the given editor view.
|
|
48
|
+
* 2. If no cache exists, initializes a new cache.
|
|
49
|
+
* 3. Updates the cache with the new attributes for the specified media node ID.
|
|
50
|
+
* 4. Sets the updated cache back to the media attributes cache.
|
|
51
|
+
* 5. Triggers a debounced update to apply the changes in the editor view.
|
|
52
|
+
*/
|
|
53
|
+
export declare const batchMediaNodeAttrsUpdate: (editorView: EditorView, props: Props) => void;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type BatchAttrsStepData } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
/**
|
|
4
|
+
* Applies a batch of attribute update steps to media nodes in the editor view.
|
|
5
|
+
*
|
|
6
|
+
* @param {EditorView} editorView - The editor view instance where the updates will be applied.
|
|
7
|
+
* @param {BatchAttrsStepData[]} steps - An array of steps containing the positions and new attributes for media nodes.
|
|
8
|
+
* @returns {boolean} - Returns false if no steps were applied or if the document remains unchanged after applying the steps.
|
|
9
|
+
*
|
|
10
|
+
* This function performs the following steps:
|
|
11
|
+
* 1. Creates a new transaction from the current editor state.
|
|
12
|
+
* 2. If there are no steps to apply, it returns false.
|
|
13
|
+
* 3. Adds a new `BatchAttrsStep` to the transaction with the provided steps.
|
|
14
|
+
* 4. If the transaction has no steps or the document remains unchanged, it returns false.
|
|
15
|
+
* 5. Dispatches the transaction to apply the updates to the editor view.
|
|
16
|
+
*
|
|
17
|
+
* TODO: use pluginInjectionAPI to batch updates from a command in a separate PR later
|
|
18
|
+
*/
|
|
19
|
+
export declare const batchStepsUpdate: (editorView: EditorView, steps: BatchAttrsStepData[]) => false | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-media",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.9",
|
|
4
4
|
"description": "Media plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@atlaskit/analytics-namespaced-context": "^6.11.0",
|
|
38
38
|
"@atlaskit/analytics-next": "^10.1.0",
|
|
39
39
|
"@atlaskit/button": "^20.1.0",
|
|
40
|
-
"@atlaskit/editor-common": "^88.
|
|
40
|
+
"@atlaskit/editor-common": "^88.5.0",
|
|
41
41
|
"@atlaskit/editor-palette": "1.6.0",
|
|
42
42
|
"@atlaskit/editor-plugin-analytics": "^1.8.0",
|
|
43
43
|
"@atlaskit/editor-plugin-annotation": "1.19.3",
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"@atlaskit/editor-tables": "^2.8.0",
|
|
56
56
|
"@atlaskit/form": "^10.5.0",
|
|
57
57
|
"@atlaskit/icon": "^22.15.0",
|
|
58
|
-
"@atlaskit/media-card": "^78.
|
|
59
|
-
"@atlaskit/media-client": "^27.
|
|
60
|
-
"@atlaskit/media-client-react": "^2.
|
|
58
|
+
"@atlaskit/media-card": "^78.2.0",
|
|
59
|
+
"@atlaskit/media-client": "^27.6.0",
|
|
60
|
+
"@atlaskit/media-client-react": "^2.2.0",
|
|
61
61
|
"@atlaskit/media-common": "^11.4.0",
|
|
62
62
|
"@atlaskit/media-filmstrip": "^47.2.0",
|
|
63
63
|
"@atlaskit/media-picker": "^66.5.0",
|
|
@@ -149,6 +149,9 @@
|
|
|
149
149
|
},
|
|
150
150
|
"platform_editor_insert_media_plugin_phase_one": {
|
|
151
151
|
"type": "boolean"
|
|
152
|
+
},
|
|
153
|
+
"platform_editor_media_batch_updates": {
|
|
154
|
+
"type": "boolean"
|
|
152
155
|
}
|
|
153
156
|
},
|
|
154
157
|
"stricter": {
|