@atlaskit/editor-plugin-synced-block 8.0.0 → 8.0.2
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,18 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-synced-block
|
|
2
2
|
|
|
3
|
+
## 8.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`720144a6aaf86`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/720144a6aaf86) -
|
|
8
|
+
[ux] Do not show confirm modal when source sync block without references is deleted.
|
|
9
|
+
|
|
10
|
+
## 8.0.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
|
|
3
16
|
## 8.0.0
|
|
4
17
|
|
|
5
18
|
### Major Changes
|
|
@@ -10,6 +10,7 @@ exports.DeleteConfirmationModal = void 0;
|
|
|
10
10
|
require("./DeleteConfirmationModal.compiled.css");
|
|
11
11
|
var _runtime = require("@compiled/react/runtime");
|
|
12
12
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
13
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
13
14
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
14
15
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
15
16
|
var _react = _interopRequireWildcard(require("react"));
|
|
@@ -24,6 +25,8 @@ var _compiled = require("@atlaskit/primitives/compiled");
|
|
|
24
25
|
var _spinner = _interopRequireDefault(require("@atlaskit/spinner"));
|
|
25
26
|
var _main = require("../pm-plugins/main");
|
|
26
27
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
28
|
+
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; }
|
|
29
|
+
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; }
|
|
27
30
|
var modalContentMapOld = {
|
|
28
31
|
'source-block-deleted': {
|
|
29
32
|
titleMultiple: _messages.syncBlockMessages.deleteConfirmationModalTitleMultiple,
|
|
@@ -74,7 +77,7 @@ var styles = {
|
|
|
74
77
|
spinner: "_1mou1wug _195g1wug"
|
|
75
78
|
};
|
|
76
79
|
var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
77
|
-
var _api$core2, _api$
|
|
80
|
+
var _api$core2, _api$core5, _api$core8;
|
|
78
81
|
var syncBlockStoreManager = _ref.syncBlockStoreManager,
|
|
79
82
|
api = _ref.api;
|
|
80
83
|
var _useState = (0, _react.useState)(false),
|
|
@@ -107,6 +110,12 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
|
|
|
107
110
|
var _useIntl = (0, _reactIntl.useIntl)(),
|
|
108
111
|
formatMessage = _useIntl.formatMessage;
|
|
109
112
|
var resolverRef = _react.default.useRef(undefined);
|
|
113
|
+
|
|
114
|
+
// When platform_synced_block_patch_9 is on and a source block with no references is deleted,
|
|
115
|
+
// the modal is never shown but onDeleteCompleted still sets bodiedSyncBlockDeletionStatus to
|
|
116
|
+
// 'completed'. This ref signals the useEffect to silently reset the status without trying to
|
|
117
|
+
// close the modal (which was never open).
|
|
118
|
+
var skipModalOnCompletedRef = _react.default.useRef(false);
|
|
110
119
|
var handleClick = (0, _react.useCallback)(function (confirm) {
|
|
111
120
|
return function () {
|
|
112
121
|
var _api$core;
|
|
@@ -127,27 +136,145 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
|
|
|
127
136
|
});
|
|
128
137
|
};
|
|
129
138
|
}, [api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions]);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
139
|
+
|
|
140
|
+
// Store activeFlag in a ref so confirmationCallback always reads the latest value
|
|
141
|
+
// even if it changes during the await fetchReferenceCountRef call.
|
|
142
|
+
var activeFlagRef = _react.default.useRef(activeFlag);
|
|
143
|
+
activeFlagRef.current = activeFlag;
|
|
144
|
+
|
|
145
|
+
// Use a ref so fetchReferenceCount can be called from confirmationCallback without
|
|
146
|
+
// being added to its dependency array — preventing confirmationCallback from being
|
|
147
|
+
// recreated mid-flight during an await (which would break the promise chain).
|
|
148
|
+
// The assignment during render is intentional — this is a standard React ref-as-latest-value
|
|
149
|
+
// pattern. The reduce over syncBlockIds (typically 1-2 items) is not actually expensive.
|
|
150
|
+
var fetchReferenceCountRef = _react.default.useRef(function () {
|
|
151
|
+
return Promise.resolve(0);
|
|
152
|
+
});
|
|
153
|
+
fetchReferenceCountRef.current = /*#__PURE__*/function () {
|
|
154
|
+
var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(syncBlockIds) {
|
|
155
|
+
var references;
|
|
156
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
157
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
158
|
+
case 0:
|
|
159
|
+
_context2.next = 2;
|
|
160
|
+
return Promise.all(syncBlockIds.map( /*#__PURE__*/function () {
|
|
161
|
+
var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(syncBlockId) {
|
|
162
|
+
var _result$references$le, _result$references;
|
|
163
|
+
var result;
|
|
164
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
165
|
+
while (1) switch (_context.prev = _context.next) {
|
|
166
|
+
case 0:
|
|
167
|
+
_context.next = 2;
|
|
168
|
+
return syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
169
|
+
case 2:
|
|
170
|
+
result = _context.sent;
|
|
171
|
+
if (!(result !== null && result !== void 0 && result.error)) {
|
|
172
|
+
_context.next = 5;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
throw new Error();
|
|
176
|
+
case 5:
|
|
177
|
+
return _context.abrupt("return", (_result$references$le = (_result$references = result.references) === null || _result$references === void 0 ? void 0 : _result$references.length) !== null && _result$references$le !== void 0 ? _result$references$le : 0);
|
|
178
|
+
case 6:
|
|
179
|
+
case "end":
|
|
180
|
+
return _context.stop();
|
|
181
|
+
}
|
|
182
|
+
}, _callee);
|
|
183
|
+
}));
|
|
184
|
+
return function (_x2) {
|
|
185
|
+
return _ref4.apply(this, arguments);
|
|
186
|
+
};
|
|
187
|
+
}()));
|
|
188
|
+
case 2:
|
|
189
|
+
references = _context2.sent;
|
|
190
|
+
return _context2.abrupt("return", references.reduce(function (sum, count) {
|
|
191
|
+
return sum + count;
|
|
192
|
+
}, 0));
|
|
193
|
+
case 4:
|
|
194
|
+
case "end":
|
|
195
|
+
return _context2.stop();
|
|
196
|
+
}
|
|
197
|
+
}, _callee2);
|
|
198
|
+
}));
|
|
199
|
+
return function (_x) {
|
|
200
|
+
return _ref3.apply(this, arguments);
|
|
201
|
+
};
|
|
202
|
+
}();
|
|
203
|
+
var confirmationCallback = (0, _react.useCallback)( /*#__PURE__*/function () {
|
|
204
|
+
var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(syncBlockIds, deleteReason) {
|
|
205
|
+
var count, _api$core3, confirmedPromise, _api$core4;
|
|
206
|
+
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
207
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
208
|
+
case 0:
|
|
209
|
+
if (!(0, _platformFeatureFlags.fg)('platform_synced_block_patch_9')) {
|
|
210
|
+
_context3.next = 15;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
_context3.prev = 1;
|
|
214
|
+
_context3.next = 4;
|
|
215
|
+
return fetchReferenceCountRef.current(syncBlockIds);
|
|
216
|
+
case 4:
|
|
217
|
+
count = _context3.sent;
|
|
218
|
+
_context3.next = 10;
|
|
219
|
+
break;
|
|
220
|
+
case 7:
|
|
221
|
+
_context3.prev = 7;
|
|
222
|
+
_context3.t0 = _context3["catch"](1);
|
|
223
|
+
count = 1;
|
|
224
|
+
case 10:
|
|
225
|
+
if (!(count === 0)) {
|
|
226
|
+
_context3.next = 14;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
// No references — auto-confirm without showing the modal.
|
|
230
|
+
// Clear activeFlag to avoid issues with subsequent deletion attempts.
|
|
231
|
+
// We do NOT reset bodiedSyncBlockDeletionStatus here because onDeleteCompleted
|
|
232
|
+
// will set it to 'completed' after the delete call returns. Instead we use a
|
|
233
|
+
// ref to signal that the next 'completed' status should be silently reset
|
|
234
|
+
// without trying to close the modal.
|
|
235
|
+
skipModalOnCompletedRef.current = true;
|
|
236
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref6) {
|
|
237
|
+
var tr = _ref6.tr;
|
|
238
|
+
return tr.setMeta(_main.syncedBlockPluginKey, _objectSpread({}, activeFlagRef.current ? {
|
|
239
|
+
activeFlag: false
|
|
240
|
+
} : {}));
|
|
241
|
+
});
|
|
242
|
+
return _context3.abrupt("return", true);
|
|
243
|
+
case 14:
|
|
244
|
+
setReferenceCount(count);
|
|
245
|
+
case 15:
|
|
246
|
+
setIsOpen(true);
|
|
247
|
+
setSyncBlockIds(syncBlockIds);
|
|
248
|
+
if (deleteReason) {
|
|
249
|
+
setDeleteReason(deleteReason);
|
|
250
|
+
}
|
|
251
|
+
confirmedPromise = new Promise(function (resolve) {
|
|
252
|
+
resolverRef.current = resolve;
|
|
253
|
+
});
|
|
254
|
+
if (activeFlagRef.current) {
|
|
255
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref7) {
|
|
256
|
+
var tr = _ref7.tr;
|
|
257
|
+
return tr.setMeta(_main.syncedBlockPluginKey, {
|
|
258
|
+
// Clear flag to avoid potential retry deletion of different blocks
|
|
259
|
+
activeFlag: false
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return _context3.abrupt("return", confirmedPromise);
|
|
264
|
+
case 21:
|
|
265
|
+
case "end":
|
|
266
|
+
return _context3.stop();
|
|
267
|
+
}
|
|
268
|
+
}, _callee3, null, [[1, 7]]);
|
|
269
|
+
}));
|
|
270
|
+
return function (_x3, _x4) {
|
|
271
|
+
return _ref5.apply(this, arguments);
|
|
272
|
+
};
|
|
273
|
+
}(),
|
|
274
|
+
// fetchReferenceCountRef and activeFlagRef are intentionally omitted — they are refs
|
|
275
|
+
// and never change identity, ensuring confirmationCallback is never recreated mid-flight
|
|
276
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
277
|
+
[api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions]);
|
|
151
278
|
(0, _react.useEffect)(function () {
|
|
152
279
|
var unregister = syncBlockStoreManager.sourceManager.registerConfirmationCallback(confirmationCallback);
|
|
153
280
|
return function () {
|
|
@@ -155,85 +282,79 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
|
|
|
155
282
|
};
|
|
156
283
|
}, [syncBlockStoreManager, confirmationCallback]);
|
|
157
284
|
(0, _react.useEffect)(function () {
|
|
285
|
+
if (skipModalOnCompletedRef.current && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_9')) {
|
|
286
|
+
if (bodiedSyncBlockDeletionStatus === 'completed') {
|
|
287
|
+
var _api$core6;
|
|
288
|
+
// Deletion was auto-confirmed without showing the modal (no references).
|
|
289
|
+
// Reset the status to 'none' — keep skipModalOnCompletedRef true until
|
|
290
|
+
// we confirm the status has landed as 'none' to guard against the race where
|
|
291
|
+
// the next deletion opens the modal before this transaction is processed.
|
|
292
|
+
api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref8) {
|
|
293
|
+
var tr = _ref8.tr;
|
|
294
|
+
return tr.setMeta(_main.syncedBlockPluginKey, {
|
|
295
|
+
bodiedSyncBlockDeletionStatus: 'none'
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
} else if (bodiedSyncBlockDeletionStatus === 'none') {
|
|
299
|
+
skipModalOnCompletedRef.current = false;
|
|
300
|
+
} else if (bodiedSyncBlockDeletionStatus === 'processing' && isOpen) {
|
|
301
|
+
// Reset on deletion failure (e.g. network error) to avoid modal stuck in opened state.
|
|
302
|
+
skipModalOnCompletedRef.current = false;
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
158
306
|
if (bodiedSyncBlockDeletionStatus === 'completed' && isOpen) {
|
|
159
|
-
var _api$
|
|
307
|
+
var _api$core7;
|
|
160
308
|
// auto close modal once deletion is successful
|
|
161
309
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
162
310
|
setIsOpen(false);
|
|
163
|
-
api === null || api === void 0 || (_api$
|
|
164
|
-
var tr =
|
|
311
|
+
api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref9) {
|
|
312
|
+
var tr = _ref9.tr;
|
|
165
313
|
return tr.setMeta(_main.syncedBlockPluginKey, {
|
|
166
314
|
// Reset deletion status to have a clean state for next deletion
|
|
167
315
|
bodiedSyncBlockDeletionStatus: 'none'
|
|
168
316
|
});
|
|
169
317
|
});
|
|
170
318
|
}
|
|
171
|
-
}, [api === null || api === void 0 || (_api$
|
|
319
|
+
}, [api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 ? void 0 : _api$core8.actions, bodiedSyncBlockDeletionStatus, isOpen]);
|
|
172
320
|
(0, _react.useEffect)(function () {
|
|
173
|
-
|
|
321
|
+
// When the flag is off, fetch references after the modal opens (original behaviour).
|
|
322
|
+
// When the flag is on, references are fetched and set before the modal opens in
|
|
323
|
+
// confirmationCallback, so this useEffect is skipped to avoid a duplicate fetch.
|
|
324
|
+
if (isOpen && syncBlockIds !== undefined && !(0, _platformFeatureFlags.fg)('platform_synced_block_patch_9')) {
|
|
174
325
|
var fetchReferences = /*#__PURE__*/function () {
|
|
175
|
-
var
|
|
176
|
-
var
|
|
177
|
-
return _regenerator.default.wrap(function
|
|
178
|
-
while (1) switch (
|
|
326
|
+
var _ref0 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
327
|
+
var totalCount;
|
|
328
|
+
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
329
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
179
330
|
case 0:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return
|
|
183
|
-
var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(syncBlockId) {
|
|
184
|
-
var _references$reference, _references$reference2;
|
|
185
|
-
var references;
|
|
186
|
-
return _regenerator.default.wrap(function _callee$(_context) {
|
|
187
|
-
while (1) switch (_context.prev = _context.next) {
|
|
188
|
-
case 0:
|
|
189
|
-
_context.next = 2;
|
|
190
|
-
return syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
191
|
-
case 2:
|
|
192
|
-
references = _context.sent;
|
|
193
|
-
if (!(references !== null && references !== void 0 && references.error)) {
|
|
194
|
-
_context.next = 5;
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
throw new Error();
|
|
198
|
-
case 5:
|
|
199
|
-
return _context.abrupt("return", (_references$reference = (_references$reference2 = references.references) === null || _references$reference2 === void 0 ? void 0 : _references$reference2.length) !== null && _references$reference !== void 0 ? _references$reference : 0);
|
|
200
|
-
case 6:
|
|
201
|
-
case "end":
|
|
202
|
-
return _context.stop();
|
|
203
|
-
}
|
|
204
|
-
}, _callee);
|
|
205
|
-
}));
|
|
206
|
-
return function (_x) {
|
|
207
|
-
return _ref6.apply(this, arguments);
|
|
208
|
-
};
|
|
209
|
-
}()));
|
|
331
|
+
_context4.prev = 0;
|
|
332
|
+
_context4.next = 3;
|
|
333
|
+
return fetchReferenceCountRef.current(syncBlockIds);
|
|
210
334
|
case 3:
|
|
211
|
-
|
|
212
|
-
totalCount = references.reduce(function (sum, count) {
|
|
213
|
-
return sum + count;
|
|
214
|
-
}, 0);
|
|
335
|
+
totalCount = _context4.sent;
|
|
215
336
|
setReferenceCount(totalCount);
|
|
216
|
-
|
|
337
|
+
_context4.next = 10;
|
|
217
338
|
break;
|
|
218
|
-
case
|
|
219
|
-
|
|
220
|
-
|
|
339
|
+
case 7:
|
|
340
|
+
_context4.prev = 7;
|
|
341
|
+
_context4.t0 = _context4["catch"](0);
|
|
221
342
|
setReferenceCount(0);
|
|
222
|
-
case
|
|
343
|
+
case 10:
|
|
223
344
|
case "end":
|
|
224
|
-
return
|
|
345
|
+
return _context4.stop();
|
|
225
346
|
}
|
|
226
|
-
},
|
|
347
|
+
}, _callee4, null, [[0, 7]]);
|
|
227
348
|
}));
|
|
228
349
|
return function fetchReferences() {
|
|
229
|
-
return
|
|
350
|
+
return _ref0.apply(this, arguments);
|
|
230
351
|
};
|
|
231
352
|
}();
|
|
232
353
|
|
|
233
354
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
234
355
|
fetchReferences();
|
|
235
356
|
}
|
|
236
|
-
}, [isOpen, syncBlockIds
|
|
357
|
+
}, [isOpen, syncBlockIds]);
|
|
237
358
|
return /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTransition, null, isOpen && /*#__PURE__*/_react.default.createElement(_modalDialog.default, {
|
|
238
359
|
onClose: handleClick(false),
|
|
239
360
|
testId: "sync-block-delete-confirmation",
|
|
@@ -253,15 +374,15 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
|
|
|
253
374
|
sourceCount: (syncBlockIds === null || syncBlockIds === void 0 ? void 0 : syncBlockIds.length) || 0
|
|
254
375
|
}))));
|
|
255
376
|
};
|
|
256
|
-
var ModalContent = function ModalContent(
|
|
257
|
-
var content =
|
|
258
|
-
referenceCount =
|
|
259
|
-
handleClick =
|
|
260
|
-
formatMessage =
|
|
261
|
-
isDeleting =
|
|
262
|
-
isDisabled =
|
|
263
|
-
deleteReason =
|
|
264
|
-
sourceCount =
|
|
377
|
+
var ModalContent = function ModalContent(_ref1) {
|
|
378
|
+
var content = _ref1.content,
|
|
379
|
+
referenceCount = _ref1.referenceCount,
|
|
380
|
+
handleClick = _ref1.handleClick,
|
|
381
|
+
formatMessage = _ref1.formatMessage,
|
|
382
|
+
isDeleting = _ref1.isDeleting,
|
|
383
|
+
isDisabled = _ref1.isDisabled,
|
|
384
|
+
deleteReason = _ref1.deleteReason,
|
|
385
|
+
sourceCount = _ref1.sourceCount;
|
|
265
386
|
var titleMultiple = content.titleMultiple,
|
|
266
387
|
titleSingle = content.titleSingle,
|
|
267
388
|
descriptionSingle = content.descriptionSingle,
|
|
@@ -65,7 +65,7 @@ export const DeleteConfirmationModal = ({
|
|
|
65
65
|
syncBlockStoreManager,
|
|
66
66
|
api
|
|
67
67
|
}) => {
|
|
68
|
-
var _api$core2, _api$
|
|
68
|
+
var _api$core2, _api$core5, _api$core8;
|
|
69
69
|
const [isOpen, setIsOpen] = useState(false);
|
|
70
70
|
const [syncBlockIds, setSyncBlockIds] = useState(undefined);
|
|
71
71
|
const [referenceCount, setReferenceCount] = useState(undefined);
|
|
@@ -86,6 +86,12 @@ export const DeleteConfirmationModal = ({
|
|
|
86
86
|
formatMessage
|
|
87
87
|
} = useIntl();
|
|
88
88
|
const resolverRef = React.useRef(undefined);
|
|
89
|
+
|
|
90
|
+
// When platform_synced_block_patch_9 is on and a source block with no references is deleted,
|
|
91
|
+
// the modal is never shown but onDeleteCompleted still sets bodiedSyncBlockDeletionStatus to
|
|
92
|
+
// 'completed'. This ref signals the useEffect to silently reset the status without trying to
|
|
93
|
+
// close the modal (which was never open).
|
|
94
|
+
const skipModalOnCompletedRef = React.useRef(false);
|
|
89
95
|
const handleClick = useCallback(confirm => () => {
|
|
90
96
|
var _api$core;
|
|
91
97
|
if (resolverRef.current) {
|
|
@@ -105,7 +111,64 @@ export const DeleteConfirmationModal = ({
|
|
|
105
111
|
});
|
|
106
112
|
});
|
|
107
113
|
}, [api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions]);
|
|
108
|
-
|
|
114
|
+
|
|
115
|
+
// Store activeFlag in a ref so confirmationCallback always reads the latest value
|
|
116
|
+
// even if it changes during the await fetchReferenceCountRef call.
|
|
117
|
+
const activeFlagRef = React.useRef(activeFlag);
|
|
118
|
+
activeFlagRef.current = activeFlag;
|
|
119
|
+
|
|
120
|
+
// Use a ref so fetchReferenceCount can be called from confirmationCallback without
|
|
121
|
+
// being added to its dependency array — preventing confirmationCallback from being
|
|
122
|
+
// recreated mid-flight during an await (which would break the promise chain).
|
|
123
|
+
// The assignment during render is intentional — this is a standard React ref-as-latest-value
|
|
124
|
+
// pattern. The reduce over syncBlockIds (typically 1-2 items) is not actually expensive.
|
|
125
|
+
const fetchReferenceCountRef = React.useRef(() => Promise.resolve(0));
|
|
126
|
+
fetchReferenceCountRef.current = async syncBlockIds => {
|
|
127
|
+
const references = await Promise.all(syncBlockIds.map(async syncBlockId => {
|
|
128
|
+
var _result$references$le, _result$references;
|
|
129
|
+
const result = await syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
130
|
+
if (result !== null && result !== void 0 && result.error) {
|
|
131
|
+
// Consider fetch fails as soon as one of the fetches fails
|
|
132
|
+
throw new Error();
|
|
133
|
+
}
|
|
134
|
+
return (_result$references$le = (_result$references = result.references) === null || _result$references === void 0 ? void 0 : _result$references.length) !== null && _result$references$le !== void 0 ? _result$references$le : 0;
|
|
135
|
+
}));
|
|
136
|
+
// eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render
|
|
137
|
+
return references.reduce((sum, count) => sum + count, 0);
|
|
138
|
+
};
|
|
139
|
+
const confirmationCallback = useCallback(async (syncBlockIds, deleteReason) => {
|
|
140
|
+
if (fg('platform_synced_block_patch_9')) {
|
|
141
|
+
// Fetch references before opening the modal. If none exist, skip the modal
|
|
142
|
+
// entirely and auto-confirm the deletion. On fetch error, default to showing
|
|
143
|
+
// the modal to avoid accidental data loss.
|
|
144
|
+
let count;
|
|
145
|
+
try {
|
|
146
|
+
count = await fetchReferenceCountRef.current(syncBlockIds);
|
|
147
|
+
} catch {
|
|
148
|
+
count = 1;
|
|
149
|
+
}
|
|
150
|
+
if (count === 0) {
|
|
151
|
+
var _api$core3;
|
|
152
|
+
// No references — auto-confirm without showing the modal.
|
|
153
|
+
// Clear activeFlag to avoid issues with subsequent deletion attempts.
|
|
154
|
+
// We do NOT reset bodiedSyncBlockDeletionStatus here because onDeleteCompleted
|
|
155
|
+
// will set it to 'completed' after the delete call returns. Instead we use a
|
|
156
|
+
// ref to signal that the next 'completed' status should be silently reset
|
|
157
|
+
// without trying to close the modal.
|
|
158
|
+
skipModalOnCompletedRef.current = true;
|
|
159
|
+
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
|
|
160
|
+
tr
|
|
161
|
+
}) => {
|
|
162
|
+
return tr.setMeta(syncedBlockPluginKey, {
|
|
163
|
+
...(activeFlagRef.current ? {
|
|
164
|
+
activeFlag: false
|
|
165
|
+
} : {})
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
setReferenceCount(count);
|
|
171
|
+
}
|
|
109
172
|
setIsOpen(true);
|
|
110
173
|
setSyncBlockIds(syncBlockIds);
|
|
111
174
|
if (deleteReason) {
|
|
@@ -114,9 +177,9 @@ export const DeleteConfirmationModal = ({
|
|
|
114
177
|
const confirmedPromise = new Promise(resolve => {
|
|
115
178
|
resolverRef.current = resolve;
|
|
116
179
|
});
|
|
117
|
-
if (
|
|
118
|
-
var _api$
|
|
119
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
180
|
+
if (activeFlagRef.current) {
|
|
181
|
+
var _api$core4;
|
|
182
|
+
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(({
|
|
120
183
|
tr
|
|
121
184
|
}) => {
|
|
122
185
|
return tr.setMeta(syncedBlockPluginKey, {
|
|
@@ -126,7 +189,11 @@ export const DeleteConfirmationModal = ({
|
|
|
126
189
|
});
|
|
127
190
|
}
|
|
128
191
|
return confirmedPromise;
|
|
129
|
-
},
|
|
192
|
+
},
|
|
193
|
+
// fetchReferenceCountRef and activeFlagRef are intentionally omitted — they are refs
|
|
194
|
+
// and never change identity, ensuring confirmationCallback is never recreated mid-flight
|
|
195
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
196
|
+
[api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions]);
|
|
130
197
|
useEffect(() => {
|
|
131
198
|
const unregister = syncBlockStoreManager.sourceManager.registerConfirmationCallback(confirmationCallback);
|
|
132
199
|
return () => {
|
|
@@ -134,12 +201,34 @@ export const DeleteConfirmationModal = ({
|
|
|
134
201
|
};
|
|
135
202
|
}, [syncBlockStoreManager, confirmationCallback]);
|
|
136
203
|
useEffect(() => {
|
|
204
|
+
if (skipModalOnCompletedRef.current && fg('platform_synced_block_patch_9')) {
|
|
205
|
+
if (bodiedSyncBlockDeletionStatus === 'completed') {
|
|
206
|
+
var _api$core6;
|
|
207
|
+
// Deletion was auto-confirmed without showing the modal (no references).
|
|
208
|
+
// Reset the status to 'none' — keep skipModalOnCompletedRef true until
|
|
209
|
+
// we confirm the status has landed as 'none' to guard against the race where
|
|
210
|
+
// the next deletion opens the modal before this transaction is processed.
|
|
211
|
+
api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(({
|
|
212
|
+
tr
|
|
213
|
+
}) => {
|
|
214
|
+
return tr.setMeta(syncedBlockPluginKey, {
|
|
215
|
+
bodiedSyncBlockDeletionStatus: 'none'
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
} else if (bodiedSyncBlockDeletionStatus === 'none') {
|
|
219
|
+
skipModalOnCompletedRef.current = false;
|
|
220
|
+
} else if (bodiedSyncBlockDeletionStatus === 'processing' && isOpen) {
|
|
221
|
+
// Reset on deletion failure (e.g. network error) to avoid modal stuck in opened state.
|
|
222
|
+
skipModalOnCompletedRef.current = false;
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
137
226
|
if (bodiedSyncBlockDeletionStatus === 'completed' && isOpen) {
|
|
138
|
-
var _api$
|
|
227
|
+
var _api$core7;
|
|
139
228
|
// auto close modal once deletion is successful
|
|
140
229
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
141
230
|
setIsOpen(false);
|
|
142
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
231
|
+
api === null || api === void 0 ? void 0 : (_api$core7 = api.core) === null || _api$core7 === void 0 ? void 0 : _api$core7.actions.execute(({
|
|
143
232
|
tr
|
|
144
233
|
}) => {
|
|
145
234
|
return tr.setMeta(syncedBlockPluginKey, {
|
|
@@ -148,21 +237,15 @@ export const DeleteConfirmationModal = ({
|
|
|
148
237
|
});
|
|
149
238
|
});
|
|
150
239
|
}
|
|
151
|
-
}, [api === null || api === void 0 ? void 0 : (_api$
|
|
240
|
+
}, [api === null || api === void 0 ? void 0 : (_api$core8 = api.core) === null || _api$core8 === void 0 ? void 0 : _api$core8.actions, bodiedSyncBlockDeletionStatus, isOpen]);
|
|
152
241
|
useEffect(() => {
|
|
153
|
-
|
|
242
|
+
// When the flag is off, fetch references after the modal opens (original behaviour).
|
|
243
|
+
// When the flag is on, references are fetched and set before the modal opens in
|
|
244
|
+
// confirmationCallback, so this useEffect is skipped to avoid a duplicate fetch.
|
|
245
|
+
if (isOpen && syncBlockIds !== undefined && !fg('platform_synced_block_patch_9')) {
|
|
154
246
|
const fetchReferences = async () => {
|
|
155
247
|
try {
|
|
156
|
-
const
|
|
157
|
-
var _references$reference, _references$reference2;
|
|
158
|
-
const references = await syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
159
|
-
if (references !== null && references !== void 0 && references.error) {
|
|
160
|
-
// Consider fetch fails as soon as one of the fetches fails
|
|
161
|
-
throw new Error();
|
|
162
|
-
}
|
|
163
|
-
return (_references$reference = (_references$reference2 = references.references) === null || _references$reference2 === void 0 ? void 0 : _references$reference2.length) !== null && _references$reference !== void 0 ? _references$reference : 0;
|
|
164
|
-
}));
|
|
165
|
-
const totalCount = references.reduce((sum, count) => sum + count, 0);
|
|
248
|
+
const totalCount = await fetchReferenceCountRef.current(syncBlockIds);
|
|
166
249
|
setReferenceCount(totalCount);
|
|
167
250
|
} catch {
|
|
168
251
|
setReferenceCount(0);
|
|
@@ -172,7 +255,7 @@ export const DeleteConfirmationModal = ({
|
|
|
172
255
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
173
256
|
fetchReferences();
|
|
174
257
|
}
|
|
175
|
-
}, [isOpen, syncBlockIds
|
|
258
|
+
}, [isOpen, syncBlockIds]);
|
|
176
259
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
177
260
|
onClose: handleClick(false),
|
|
178
261
|
testId: "sync-block-delete-confirmation",
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/* DeleteConfirmationModal.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
3
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
4
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
5
|
import "./DeleteConfirmationModal.compiled.css";
|
|
5
6
|
import { ax, ix } from "@compiled/react/runtime";
|
|
7
|
+
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; }
|
|
8
|
+
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
9
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
7
10
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
8
11
|
import { useIntl } from 'react-intl';
|
|
@@ -65,7 +68,7 @@ var styles = {
|
|
|
65
68
|
spinner: "_1mou1wug _195g1wug"
|
|
66
69
|
};
|
|
67
70
|
export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
68
|
-
var _api$core2, _api$
|
|
71
|
+
var _api$core2, _api$core5, _api$core8;
|
|
69
72
|
var syncBlockStoreManager = _ref.syncBlockStoreManager,
|
|
70
73
|
api = _ref.api;
|
|
71
74
|
var _useState = useState(false),
|
|
@@ -98,6 +101,12 @@ export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
|
98
101
|
var _useIntl = useIntl(),
|
|
99
102
|
formatMessage = _useIntl.formatMessage;
|
|
100
103
|
var resolverRef = React.useRef(undefined);
|
|
104
|
+
|
|
105
|
+
// When platform_synced_block_patch_9 is on and a source block with no references is deleted,
|
|
106
|
+
// the modal is never shown but onDeleteCompleted still sets bodiedSyncBlockDeletionStatus to
|
|
107
|
+
// 'completed'. This ref signals the useEffect to silently reset the status without trying to
|
|
108
|
+
// close the modal (which was never open).
|
|
109
|
+
var skipModalOnCompletedRef = React.useRef(false);
|
|
101
110
|
var handleClick = useCallback(function (confirm) {
|
|
102
111
|
return function () {
|
|
103
112
|
var _api$core;
|
|
@@ -118,27 +127,145 @@ export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
|
118
127
|
});
|
|
119
128
|
};
|
|
120
129
|
}, [api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions]);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
|
|
131
|
+
// Store activeFlag in a ref so confirmationCallback always reads the latest value
|
|
132
|
+
// even if it changes during the await fetchReferenceCountRef call.
|
|
133
|
+
var activeFlagRef = React.useRef(activeFlag);
|
|
134
|
+
activeFlagRef.current = activeFlag;
|
|
135
|
+
|
|
136
|
+
// Use a ref so fetchReferenceCount can be called from confirmationCallback without
|
|
137
|
+
// being added to its dependency array — preventing confirmationCallback from being
|
|
138
|
+
// recreated mid-flight during an await (which would break the promise chain).
|
|
139
|
+
// The assignment during render is intentional — this is a standard React ref-as-latest-value
|
|
140
|
+
// pattern. The reduce over syncBlockIds (typically 1-2 items) is not actually expensive.
|
|
141
|
+
var fetchReferenceCountRef = React.useRef(function () {
|
|
142
|
+
return Promise.resolve(0);
|
|
143
|
+
});
|
|
144
|
+
fetchReferenceCountRef.current = /*#__PURE__*/function () {
|
|
145
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(syncBlockIds) {
|
|
146
|
+
var references;
|
|
147
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
148
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
149
|
+
case 0:
|
|
150
|
+
_context2.next = 2;
|
|
151
|
+
return Promise.all(syncBlockIds.map( /*#__PURE__*/function () {
|
|
152
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(syncBlockId) {
|
|
153
|
+
var _result$references$le, _result$references;
|
|
154
|
+
var result;
|
|
155
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
156
|
+
while (1) switch (_context.prev = _context.next) {
|
|
157
|
+
case 0:
|
|
158
|
+
_context.next = 2;
|
|
159
|
+
return syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
160
|
+
case 2:
|
|
161
|
+
result = _context.sent;
|
|
162
|
+
if (!(result !== null && result !== void 0 && result.error)) {
|
|
163
|
+
_context.next = 5;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
throw new Error();
|
|
167
|
+
case 5:
|
|
168
|
+
return _context.abrupt("return", (_result$references$le = (_result$references = result.references) === null || _result$references === void 0 ? void 0 : _result$references.length) !== null && _result$references$le !== void 0 ? _result$references$le : 0);
|
|
169
|
+
case 6:
|
|
170
|
+
case "end":
|
|
171
|
+
return _context.stop();
|
|
172
|
+
}
|
|
173
|
+
}, _callee);
|
|
174
|
+
}));
|
|
175
|
+
return function (_x2) {
|
|
176
|
+
return _ref4.apply(this, arguments);
|
|
177
|
+
};
|
|
178
|
+
}()));
|
|
179
|
+
case 2:
|
|
180
|
+
references = _context2.sent;
|
|
181
|
+
return _context2.abrupt("return", references.reduce(function (sum, count) {
|
|
182
|
+
return sum + count;
|
|
183
|
+
}, 0));
|
|
184
|
+
case 4:
|
|
185
|
+
case "end":
|
|
186
|
+
return _context2.stop();
|
|
187
|
+
}
|
|
188
|
+
}, _callee2);
|
|
189
|
+
}));
|
|
190
|
+
return function (_x) {
|
|
191
|
+
return _ref3.apply(this, arguments);
|
|
192
|
+
};
|
|
193
|
+
}();
|
|
194
|
+
var confirmationCallback = useCallback( /*#__PURE__*/function () {
|
|
195
|
+
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(syncBlockIds, deleteReason) {
|
|
196
|
+
var count, _api$core3, confirmedPromise, _api$core4;
|
|
197
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
198
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
199
|
+
case 0:
|
|
200
|
+
if (!fg('platform_synced_block_patch_9')) {
|
|
201
|
+
_context3.next = 15;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
_context3.prev = 1;
|
|
205
|
+
_context3.next = 4;
|
|
206
|
+
return fetchReferenceCountRef.current(syncBlockIds);
|
|
207
|
+
case 4:
|
|
208
|
+
count = _context3.sent;
|
|
209
|
+
_context3.next = 10;
|
|
210
|
+
break;
|
|
211
|
+
case 7:
|
|
212
|
+
_context3.prev = 7;
|
|
213
|
+
_context3.t0 = _context3["catch"](1);
|
|
214
|
+
count = 1;
|
|
215
|
+
case 10:
|
|
216
|
+
if (!(count === 0)) {
|
|
217
|
+
_context3.next = 14;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
// No references — auto-confirm without showing the modal.
|
|
221
|
+
// Clear activeFlag to avoid issues with subsequent deletion attempts.
|
|
222
|
+
// We do NOT reset bodiedSyncBlockDeletionStatus here because onDeleteCompleted
|
|
223
|
+
// will set it to 'completed' after the delete call returns. Instead we use a
|
|
224
|
+
// ref to signal that the next 'completed' status should be silently reset
|
|
225
|
+
// without trying to close the modal.
|
|
226
|
+
skipModalOnCompletedRef.current = true;
|
|
227
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref6) {
|
|
228
|
+
var tr = _ref6.tr;
|
|
229
|
+
return tr.setMeta(syncedBlockPluginKey, _objectSpread({}, activeFlagRef.current ? {
|
|
230
|
+
activeFlag: false
|
|
231
|
+
} : {}));
|
|
232
|
+
});
|
|
233
|
+
return _context3.abrupt("return", true);
|
|
234
|
+
case 14:
|
|
235
|
+
setReferenceCount(count);
|
|
236
|
+
case 15:
|
|
237
|
+
setIsOpen(true);
|
|
238
|
+
setSyncBlockIds(syncBlockIds);
|
|
239
|
+
if (deleteReason) {
|
|
240
|
+
setDeleteReason(deleteReason);
|
|
241
|
+
}
|
|
242
|
+
confirmedPromise = new Promise(function (resolve) {
|
|
243
|
+
resolverRef.current = resolve;
|
|
244
|
+
});
|
|
245
|
+
if (activeFlagRef.current) {
|
|
246
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref7) {
|
|
247
|
+
var tr = _ref7.tr;
|
|
248
|
+
return tr.setMeta(syncedBlockPluginKey, {
|
|
249
|
+
// Clear flag to avoid potential retry deletion of different blocks
|
|
250
|
+
activeFlag: false
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return _context3.abrupt("return", confirmedPromise);
|
|
255
|
+
case 21:
|
|
256
|
+
case "end":
|
|
257
|
+
return _context3.stop();
|
|
258
|
+
}
|
|
259
|
+
}, _callee3, null, [[1, 7]]);
|
|
260
|
+
}));
|
|
261
|
+
return function (_x3, _x4) {
|
|
262
|
+
return _ref5.apply(this, arguments);
|
|
263
|
+
};
|
|
264
|
+
}(),
|
|
265
|
+
// fetchReferenceCountRef and activeFlagRef are intentionally omitted — they are refs
|
|
266
|
+
// and never change identity, ensuring confirmationCallback is never recreated mid-flight
|
|
267
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
268
|
+
[api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions]);
|
|
142
269
|
useEffect(function () {
|
|
143
270
|
var unregister = syncBlockStoreManager.sourceManager.registerConfirmationCallback(confirmationCallback);
|
|
144
271
|
return function () {
|
|
@@ -146,85 +273,79 @@ export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
|
146
273
|
};
|
|
147
274
|
}, [syncBlockStoreManager, confirmationCallback]);
|
|
148
275
|
useEffect(function () {
|
|
276
|
+
if (skipModalOnCompletedRef.current && fg('platform_synced_block_patch_9')) {
|
|
277
|
+
if (bodiedSyncBlockDeletionStatus === 'completed') {
|
|
278
|
+
var _api$core6;
|
|
279
|
+
// Deletion was auto-confirmed without showing the modal (no references).
|
|
280
|
+
// Reset the status to 'none' — keep skipModalOnCompletedRef true until
|
|
281
|
+
// we confirm the status has landed as 'none' to guard against the race where
|
|
282
|
+
// the next deletion opens the modal before this transaction is processed.
|
|
283
|
+
api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref8) {
|
|
284
|
+
var tr = _ref8.tr;
|
|
285
|
+
return tr.setMeta(syncedBlockPluginKey, {
|
|
286
|
+
bodiedSyncBlockDeletionStatus: 'none'
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
} else if (bodiedSyncBlockDeletionStatus === 'none') {
|
|
290
|
+
skipModalOnCompletedRef.current = false;
|
|
291
|
+
} else if (bodiedSyncBlockDeletionStatus === 'processing' && isOpen) {
|
|
292
|
+
// Reset on deletion failure (e.g. network error) to avoid modal stuck in opened state.
|
|
293
|
+
skipModalOnCompletedRef.current = false;
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
149
297
|
if (bodiedSyncBlockDeletionStatus === 'completed' && isOpen) {
|
|
150
|
-
var _api$
|
|
298
|
+
var _api$core7;
|
|
151
299
|
// auto close modal once deletion is successful
|
|
152
300
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
153
301
|
setIsOpen(false);
|
|
154
|
-
api === null || api === void 0 || (_api$
|
|
155
|
-
var tr =
|
|
302
|
+
api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref9) {
|
|
303
|
+
var tr = _ref9.tr;
|
|
156
304
|
return tr.setMeta(syncedBlockPluginKey, {
|
|
157
305
|
// Reset deletion status to have a clean state for next deletion
|
|
158
306
|
bodiedSyncBlockDeletionStatus: 'none'
|
|
159
307
|
});
|
|
160
308
|
});
|
|
161
309
|
}
|
|
162
|
-
}, [api === null || api === void 0 || (_api$
|
|
310
|
+
}, [api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 ? void 0 : _api$core8.actions, bodiedSyncBlockDeletionStatus, isOpen]);
|
|
163
311
|
useEffect(function () {
|
|
164
|
-
|
|
312
|
+
// When the flag is off, fetch references after the modal opens (original behaviour).
|
|
313
|
+
// When the flag is on, references are fetched and set before the modal opens in
|
|
314
|
+
// confirmationCallback, so this useEffect is skipped to avoid a duplicate fetch.
|
|
315
|
+
if (isOpen && syncBlockIds !== undefined && !fg('platform_synced_block_patch_9')) {
|
|
165
316
|
var fetchReferences = /*#__PURE__*/function () {
|
|
166
|
-
var
|
|
167
|
-
var
|
|
168
|
-
return _regeneratorRuntime.wrap(function
|
|
169
|
-
while (1) switch (
|
|
317
|
+
var _ref0 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
318
|
+
var totalCount;
|
|
319
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
320
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
170
321
|
case 0:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return
|
|
174
|
-
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(syncBlockId) {
|
|
175
|
-
var _references$reference, _references$reference2;
|
|
176
|
-
var references;
|
|
177
|
-
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
178
|
-
while (1) switch (_context.prev = _context.next) {
|
|
179
|
-
case 0:
|
|
180
|
-
_context.next = 2;
|
|
181
|
-
return syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
|
|
182
|
-
case 2:
|
|
183
|
-
references = _context.sent;
|
|
184
|
-
if (!(references !== null && references !== void 0 && references.error)) {
|
|
185
|
-
_context.next = 5;
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
throw new Error();
|
|
189
|
-
case 5:
|
|
190
|
-
return _context.abrupt("return", (_references$reference = (_references$reference2 = references.references) === null || _references$reference2 === void 0 ? void 0 : _references$reference2.length) !== null && _references$reference !== void 0 ? _references$reference : 0);
|
|
191
|
-
case 6:
|
|
192
|
-
case "end":
|
|
193
|
-
return _context.stop();
|
|
194
|
-
}
|
|
195
|
-
}, _callee);
|
|
196
|
-
}));
|
|
197
|
-
return function (_x) {
|
|
198
|
-
return _ref6.apply(this, arguments);
|
|
199
|
-
};
|
|
200
|
-
}()));
|
|
322
|
+
_context4.prev = 0;
|
|
323
|
+
_context4.next = 3;
|
|
324
|
+
return fetchReferenceCountRef.current(syncBlockIds);
|
|
201
325
|
case 3:
|
|
202
|
-
|
|
203
|
-
totalCount = references.reduce(function (sum, count) {
|
|
204
|
-
return sum + count;
|
|
205
|
-
}, 0);
|
|
326
|
+
totalCount = _context4.sent;
|
|
206
327
|
setReferenceCount(totalCount);
|
|
207
|
-
|
|
328
|
+
_context4.next = 10;
|
|
208
329
|
break;
|
|
209
|
-
case
|
|
210
|
-
|
|
211
|
-
|
|
330
|
+
case 7:
|
|
331
|
+
_context4.prev = 7;
|
|
332
|
+
_context4.t0 = _context4["catch"](0);
|
|
212
333
|
setReferenceCount(0);
|
|
213
|
-
case
|
|
334
|
+
case 10:
|
|
214
335
|
case "end":
|
|
215
|
-
return
|
|
336
|
+
return _context4.stop();
|
|
216
337
|
}
|
|
217
|
-
},
|
|
338
|
+
}, _callee4, null, [[0, 7]]);
|
|
218
339
|
}));
|
|
219
340
|
return function fetchReferences() {
|
|
220
|
-
return
|
|
341
|
+
return _ref0.apply(this, arguments);
|
|
221
342
|
};
|
|
222
343
|
}();
|
|
223
344
|
|
|
224
345
|
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
|
|
225
346
|
fetchReferences();
|
|
226
347
|
}
|
|
227
|
-
}, [isOpen, syncBlockIds
|
|
348
|
+
}, [isOpen, syncBlockIds]);
|
|
228
349
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
229
350
|
onClose: handleClick(false),
|
|
230
351
|
testId: "sync-block-delete-confirmation",
|
|
@@ -244,15 +365,15 @@ export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
|
|
|
244
365
|
sourceCount: (syncBlockIds === null || syncBlockIds === void 0 ? void 0 : syncBlockIds.length) || 0
|
|
245
366
|
}))));
|
|
246
367
|
};
|
|
247
|
-
var ModalContent = function ModalContent(
|
|
248
|
-
var content =
|
|
249
|
-
referenceCount =
|
|
250
|
-
handleClick =
|
|
251
|
-
formatMessage =
|
|
252
|
-
isDeleting =
|
|
253
|
-
isDisabled =
|
|
254
|
-
deleteReason =
|
|
255
|
-
sourceCount =
|
|
368
|
+
var ModalContent = function ModalContent(_ref1) {
|
|
369
|
+
var content = _ref1.content,
|
|
370
|
+
referenceCount = _ref1.referenceCount,
|
|
371
|
+
handleClick = _ref1.handleClick,
|
|
372
|
+
formatMessage = _ref1.formatMessage,
|
|
373
|
+
isDeleting = _ref1.isDeleting,
|
|
374
|
+
isDisabled = _ref1.isDisabled,
|
|
375
|
+
deleteReason = _ref1.deleteReason,
|
|
376
|
+
sourceCount = _ref1.sourceCount;
|
|
256
377
|
var titleMultiple = content.titleMultiple,
|
|
257
378
|
titleSingle = content.titleSingle,
|
|
258
379
|
descriptionSingle = content.descriptionSingle,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-synced-block",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.2",
|
|
4
4
|
"description": "SyncedBlock plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@atlaskit/editor-plugin-user-intent": "^8.0.0",
|
|
44
44
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
45
45
|
"@atlaskit/editor-shared-styles": "^3.10.0",
|
|
46
|
-
"@atlaskit/editor-synced-block-provider": "^6.
|
|
46
|
+
"@atlaskit/editor-synced-block-provider": "^6.1.0",
|
|
47
47
|
"@atlaskit/editor-toolbar": "^1.0.0",
|
|
48
48
|
"@atlaskit/flag": "^17.9.0",
|
|
49
49
|
"@atlaskit/icon": "34.2.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
55
55
|
"@atlaskit/primitives": "^19.0.0",
|
|
56
56
|
"@atlaskit/spinner": "19.1.2",
|
|
57
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
57
|
+
"@atlaskit/tmp-editor-statsig": "^63.0.0",
|
|
58
58
|
"@atlaskit/tokens": "13.0.0",
|
|
59
59
|
"@atlaskit/tooltip": "^21.1.0",
|
|
60
60
|
"@atlaskit/visually-hidden": "^3.0.0",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"date-fns": "^2.17.0"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@atlaskit/editor-common": "^114.
|
|
67
|
+
"@atlaskit/editor-common": "^114.2.0",
|
|
68
68
|
"react": "^18.2.0",
|
|
69
69
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
70
70
|
},
|
|
@@ -123,6 +123,9 @@
|
|
|
123
123
|
},
|
|
124
124
|
"platform_synced_block_patch_8": {
|
|
125
125
|
"type": "boolean"
|
|
126
|
+
},
|
|
127
|
+
"platform_synced_block_patch_9": {
|
|
128
|
+
"type": "boolean"
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
}
|