@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 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, _helpers.updateAllMediaNodesAttrs)(id, {
50
- __contextId: objectId
51
- })(_this.props.view.state, _this.props.view.dispatch);
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, _helpers.updateAllMediaNodesAttrs)(id, newAttrs)(_this.props.view.state, _this.props.view.dispatch);
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, _helpers.updateAllMediaNodesAttrs)(dimensions.id, {
308
- height: dimensions.height,
309
- width: dimensions.width
310
- })(_this.props.view.state, _this.props.view.dispatch);
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
- updateAllMediaNodesAttrs(id, {
27
- __contextId: objectId
28
- })(this.props.view.state, this.props.view.dispatch);
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
- updateAllMediaNodesAttrs(id, newAttrs)(this.props.view.state, this.props.view.dispatch);
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
- updateAllMediaNodesAttrs(dimensions.id, {
167
- height: dimensions.height,
168
- width: dimensions.width
169
- })(this.props.view.state, this.props.view.dispatch);
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();
@@ -290,6 +290,8 @@ export class MediaPluginStateImplementation {
290
290
  return INPUT_METHOD.CLIPBOARD;
291
291
  case 'dropzone':
292
292
  return INPUT_METHOD.DRAG_AND_DROP;
293
+ case 'browser':
294
+ return INPUT_METHOD.BROWSER;
293
295
  }
294
296
  return;
295
297
  });
@@ -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
- updateAllMediaNodesAttrs(id, {
43
- __contextId: objectId
44
- })(_this.props.view.state, _this.props.view.dispatch);
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
- updateAllMediaNodesAttrs(id, newAttrs)(_this.props.view.state, _this.props.view.dispatch);
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
- updateAllMediaNodesAttrs(dimensions.id, {
301
- height: dimensions.height,
302
- width: dimensions.width
303
- })(_this.props.view.state, _this.props.view.dispatch);
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;
@@ -316,6 +316,8 @@ export var MediaPluginStateImplementation = /*#__PURE__*/function () {
316
316
  return INPUT_METHOD.CLIPBOARD;
317
317
  case 'dropzone':
318
318
  return INPUT_METHOD.DRAG_AND_DROP;
319
+ case 'browser':
320
+ return INPUT_METHOD.BROWSER;
319
321
  }
320
322
  return;
321
323
  });
@@ -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.7",
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.2.0",
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.1.0",
59
- "@atlaskit/media-client": "^27.5.0",
60
- "@atlaskit/media-client-react": "^2.1.0",
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": {