@atlaskit/editor-plugin-mentions 13.3.15 → 14.1.0

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.
@@ -12,6 +12,8 @@ import { fg } from '@atlaskit/platform-feature-flags';
12
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
13
  import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
14
14
  import { createSingleMentionFragment } from '../../editor-commands';
15
+ import { mentionPluginKey } from '../../pm-plugins/key';
16
+ import { ACTIONS } from '../../pm-plugins/main';
15
17
  import { mentionPlaceholderPluginKey, MENTION_PLACEHOLDER_ACTIONS } from '../../pm-plugins/mentionPlaceholder';
16
18
  import { getMentionPluginState } from '../../pm-plugins/utils';
17
19
  import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
@@ -20,6 +22,7 @@ import { buildTypeAheadCancelPayload, buildTypeAheadInsertedPayload, buildTypeAh
20
22
  import { isInviteItem, isTeamStats, isTeamType, shouldKeepInviteItem } from './utils';
21
23
  const isAgentUserType = userType => userType === 'APP' || userType === 'AGENT';
22
24
  const isAgentMention = mention => isAgentUserType(mention.userType) || mention.appType === 'agent';
25
+ const isAgentTypeAheadItem = item => item.mention ? isAgentMention(item.mention) : false;
23
26
  const createInviteItem = ({
24
27
  mentionProvider,
25
28
  onInviteItemMount,
@@ -307,19 +310,25 @@ export const createTypeAheadConfig = ({
307
310
  return [{
308
311
  id: 'people',
309
312
  title: intl.formatMessage(mentionMessages.typeAheadSectionPeople),
310
- filter: item => {
311
- var _item$mention;
312
- return !isAgentUserType(((_item$mention = item.mention) === null || _item$mention === void 0 ? void 0 : _item$mention.userType) || '');
313
- },
314
- limit: expVal('platform_editor_agent_mentions', 'isEnabled', false) ? 5 : 6
313
+ filter: item => !isAgentTypeAheadItem(item),
314
+ limit: expVal('platform_editor_agent_mentions', 'isEnabled', false) ? 5 : 6,
315
+ ...(expVal('platform_editor_agent_mentions', 'isEnabled', false) ? {
316
+ sectionTitleDisplay: {
317
+ showWhenQueryPresent: false,
318
+ showWhenOnlySection: true
319
+ }
320
+ } : {})
315
321
  }, {
316
322
  id: 'agents',
317
323
  title: intl.formatMessage(mentionMessages.typeAheadSectionAgents),
318
- filter: item => {
319
- var _item$mention2;
320
- return isAgentUserType(((_item$mention2 = item.mention) === null || _item$mention2 === void 0 ? void 0 : _item$mention2.userType) || '');
321
- },
322
- limit: expVal('platform_editor_agent_mentions', 'isEnabled', false) ? 5 : undefined
324
+ filter: item => isAgentTypeAheadItem(item),
325
+ limit: expVal('platform_editor_agent_mentions', 'isEnabled', false) ? 5 : undefined,
326
+ ...(expVal('platform_editor_agent_mentions', 'isEnabled', false) ? {
327
+ sectionTitleDisplay: {
328
+ showWhenQueryPresent: false,
329
+ showWhenOnlySection: true
330
+ }
331
+ } : {})
323
332
  }];
324
333
  },
325
334
  onOpen: () => {
@@ -355,10 +364,10 @@ export const createTypeAheadConfig = ({
355
364
  sessionId
356
365
  };
357
366
  const isAgentMentionsExperimentEnabled = expVal('platform_editor_agent_mentions', 'isEnabled', false);
358
- const shouldSuppressInviteForAgentMention = isAgentMentionsExperimentEnabled && isAgentMention(item.mention);
367
+ const isAgentMentionInsertion = isAgentMentionsExperimentEnabled && isAgentMention(item.mention);
359
368
  // userType can be missing for provider-only agent mentions. Copy/paste cannot
360
369
  // see appType, so persist APP only when there is no explicit userType.
361
- const persistedUserType = isAgentMentionsExperimentEnabled && isAgentMention(item.mention) && userType == null ? 'APP' : userType;
370
+ const persistedUserType = isAgentMentionInsertion && userType == null ? 'APP' : userType;
362
371
  if (mentionProvider && !isInviteItem(item.mention)) {
363
372
  mentionProvider.recordMentionSelection(item.mention, mentionContext);
364
373
  }
@@ -417,7 +426,7 @@ export const createTypeAheadConfig = ({
417
426
  localId: mentionLocalId,
418
427
  method: 'typed',
419
428
  type: 'added',
420
- ...(shouldSuppressInviteForAgentMention ? {
429
+ ...(isAgentMentionInsertion ? {
421
430
  shouldSuppressMentionNotification: true
422
431
  } : {})
423
432
  };
@@ -430,22 +439,22 @@ export const createTypeAheadConfig = ({
430
439
  handleMentionsChanged([mentionChange]);
431
440
  }
432
441
  }
433
- fireEvent(buildTypeAheadInsertedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, item.mention, mentionLocalId, sourceListItem.map(x => x.mention), query, contextIdentifierProvider, taskListId, taskItemId));
442
+ fireEvent(buildTypeAheadInsertedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, item.mention, mentionLocalId, sourceListItem.map(x => x.mention), query, contextIdentifierProvider, taskListId, taskItemId, isAgentMentionInsertion));
434
443
 
435
444
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
436
445
  sessionId = uuid();
437
446
  if (mentionProvider && isTeamType(userType)) {
438
447
  return insert(buildNodesForTeamMention(schema, item.mention, mentionProvider, sanitizePrivateContent));
439
448
  }
440
- if (!shouldSuppressInviteForAgentMention && isXProductUser && mentionProvider && mentionProvider.inviteXProductUser) {
449
+ if (!isAgentMentionInsertion && isXProductUser && mentionProvider && mentionProvider.inviteXProductUser) {
441
450
  mentionProvider.inviteXProductUser(id, name);
442
451
  }
443
- return insert(createSingleMentionFragment({
452
+ const tr = insert(createSingleMentionFragment({
444
453
  mentionProvider,
445
454
  mentionInsertDisplayName,
446
455
  tr: state.tr,
447
456
  sanitizePrivateContent,
448
- suppressInviteXProductUser: shouldSuppressInviteForAgentMention
457
+ suppressInviteXProductUser: isAgentMentionInsertion
449
458
  })({
450
459
  name,
451
460
  id,
@@ -455,6 +464,15 @@ export const createTypeAheadConfig = ({
455
464
  accessLevel,
456
465
  isXProductUser
457
466
  }));
467
+ if (isAgentMentionInsertion) {
468
+ tr.setMeta(mentionPluginKey, {
469
+ action: ACTIONS.SET_PENDING_TYPED_AGENT_MENTION,
470
+ params: {
471
+ localId: mentionLocalId
472
+ }
473
+ });
474
+ }
475
+ return tr;
458
476
  },
459
477
  dismiss({
460
478
  editorState,
@@ -17,14 +17,17 @@ import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types'
17
17
  import { mentionPluginKey } from './key';
18
18
  import { canMentionBeCreatedInRange } from './utils';
19
19
  export var ACTIONS = {
20
+ COMMIT_PENDING_TYPED_AGENT_MENTION: 'COMMIT_PENDING_TYPED_AGENT_MENTION',
21
+ SET_PENDING_TYPED_AGENT_MENTION: 'SET_PENDING_TYPED_AGENT_MENTION',
20
22
  SET_PROVIDER: 'SET_PROVIDER'
21
23
  };
22
24
 
23
25
  // 'AGENT' is not in the ADF schema UserType enum but is used at runtime.
24
26
  var AGENT_USER_TYPES = new Set(['APP', 'AGENT']);
25
27
  var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
28
+ var AGENT_MENTION_INACTIVITY_MS = 3000;
26
29
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
27
- var PACKAGE_VERSION = "13.3.14";
30
+ var PACKAGE_VERSION = "14.0.0";
28
31
  var setProvider = function setProvider(provider) {
29
32
  return function (state, dispatch) {
30
33
  if (dispatch) {
@@ -38,11 +41,97 @@ var setProvider = function setProvider(provider) {
38
41
  return true;
39
42
  };
40
43
  };
41
- export function createMentionPlugin(_ref) {
42
- var pmPluginFactoryParams = _ref.pmPluginFactoryParams,
43
- fireEvent = _ref.fireEvent,
44
- options = _ref.options,
45
- api = _ref.api;
44
+
45
+ /**
46
+ * Returns true when a transaction represents a local user document edit that
47
+ * should restart pending agent-mention inactivity tracking.
48
+ *
49
+ * Remote/collab updates, replace-document transactions, AI streaming transforms,
50
+ * selection-only movements, and metadata-only transactions are intentionally ignored.
51
+ */
52
+ var isQualifyingLocalUserDocChange = function isQualifyingLocalUserDocChange(tr) {
53
+ var isAIStreaming = Boolean(tr.getMeta(AI_STREAMING_TRANSFORMATION_META_KEY));
54
+ return tr.docChanged && !tr.getMeta('isRemote') && !tr.getMeta('replaceDocument') && !isAIStreaming;
55
+ };
56
+
57
+ /**
58
+ * Reads agent-mention details from a known document position without traversing
59
+ * the document. Callers pass a matcher so mapped positions are only accepted
60
+ * when they still point at the same pending/tracked mention.
61
+ */
62
+ var getAgentMentionDetailsAtPos = function getAgentMentionDetailsAtPos(state, pos, matchesMention) {
63
+ var _parentNode$type$name;
64
+ if (pos < 0 || pos > state.doc.content.size) {
65
+ return null;
66
+ }
67
+ var node = state.doc.nodeAt(pos);
68
+ var mentionSchema = state.schema.nodes.mention;
69
+ if ((node === null || node === void 0 ? void 0 : node.type) !== mentionSchema || !AGENT_USER_TYPES.has(node.attrs.userType) || !matchesMention(node.attrs) || !node.attrs.id) {
70
+ return null;
71
+ }
72
+ var $mentionPos = state.doc.resolve(pos);
73
+ var parentNode = $mentionPos.node($mentionPos.depth);
74
+ return {
75
+ id: node.attrs.id,
76
+ context: parentNode.textContent.trim() || null,
77
+ nodeSize: node.nodeSize,
78
+ parentNodeType: (_parentNode$type$name = parentNode.type.name) !== null && _parentNode$type$name !== void 0 ? _parentNode$type$name : null,
79
+ pos: pos
80
+ };
81
+ };
82
+
83
+ /**
84
+ * Finds an agent mention that survived a document change when the changed-range
85
+ * scan did not find one. Prefers the previously tracked mention ID when present;
86
+ * otherwise returns a surviving agent mention using the existing traversal order.
87
+ */
88
+ var getSurvivingAgentMentionDetails = function getSurvivingAgentMentionDetails(state, preferredId) {
89
+ var mentionSchema = state.schema.nodes.mention;
90
+ var result = null;
91
+ state.doc.descendants(function (node, pos) {
92
+ var _result, _result2;
93
+ if (((_result = result) === null || _result === void 0 ? void 0 : _result.id) === preferredId) {
94
+ return false;
95
+ }
96
+ if (node.type !== mentionSchema || !AGENT_USER_TYPES.has(node.attrs.userType) || !node.attrs.id) {
97
+ return true;
98
+ }
99
+ result = getAgentMentionDetailsAtPos(state, pos, function (attrs) {
100
+ return attrs.id === node.attrs.id;
101
+ });
102
+ return ((_result2 = result) === null || _result2 === void 0 ? void 0 : _result2.id) !== preferredId;
103
+ });
104
+ return result;
105
+ };
106
+
107
+ /**
108
+ * Maps a pending typed agent mention through a document-changing transaction and
109
+ * returns the updated pending state. If the mapped position was deleted or no
110
+ * longer points at the same local mention, the pending mention is cleared.
111
+ */
112
+ var getPendingTypedAgentMentionAfterDocChange = function getPendingTypedAgentMentionAfterDocChange(state, tr, pendingTypedAgentMention, _ref) {
113
+ var resetTimer = _ref.resetTimer;
114
+ var mappedPos = tr.mapping.mapResult(pendingTypedAgentMention.pos, 1);
115
+ var resetCount = resetTimer ? pendingTypedAgentMention.resetCount + 1 : pendingTypedAgentMention.resetCount;
116
+ if (mappedPos.deleted) {
117
+ return null;
118
+ }
119
+ var pendingMentionDetails = getAgentMentionDetailsAtPos(state, mappedPos.pos, function (attrs) {
120
+ return attrs.localId === pendingTypedAgentMention.localId;
121
+ });
122
+ return pendingMentionDetails ? {
123
+ id: pendingMentionDetails.id,
124
+ localId: pendingTypedAgentMention.localId,
125
+ nodeSize: pendingMentionDetails.nodeSize,
126
+ pos: pendingMentionDetails.pos,
127
+ resetCount: resetCount
128
+ } : null;
129
+ };
130
+ export function createMentionPlugin(_ref2) {
131
+ var pmPluginFactoryParams = _ref2.pmPluginFactoryParams,
132
+ fireEvent = _ref2.fireEvent,
133
+ options = _ref2.options,
134
+ api = _ref2.api;
46
135
  var mentionProvider;
47
136
  var sendAnalytics = function sendAnalytics(event, actionSubject, action, attributes) {
48
137
  if (event === SLI_EVENT_TYPE || event === SMART_EVENT_TYPE) {
@@ -68,36 +157,74 @@ export function createMentionPlugin(_ref) {
68
157
  };
69
158
  },
70
159
  apply: function apply(tr, pluginState, oldState, newState) {
71
- var _ref2 = tr.getMeta(mentionPluginKey) || {
160
+ var _ref3 = tr.getMeta(mentionPluginKey) || {
72
161
  action: null,
73
162
  params: null
74
163
  },
75
- action = _ref2.action,
76
- params = _ref2.params;
77
- var hasNewPluginState = false;
164
+ action = _ref3.action,
165
+ params = _ref3.params;
166
+ var hasPublicPluginStateChanged = false;
78
167
  var newPluginState = pluginState;
168
+ var isAgentMentionsExperimentEnabled = editorExperiment('platform_editor_agent_mentions', true);
79
169
  var hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
80
170
  if (tr.docChanged || tr.selectionSet && hasPositionChanged) {
81
171
  newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
82
172
  canInsertMention: canMentionBeCreatedInRange(newState.selection.from, newState.selection.to)(newState)
83
173
  });
84
- hasNewPluginState = true;
174
+ hasPublicPluginStateChanged = true;
85
175
  }
86
176
  switch (action) {
177
+ case ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION:
178
+ {
179
+ var _newPluginState$lastA;
180
+ var pendingTypedAgentMention = newPluginState.pendingTypedAgentMention;
181
+ // Ignore stale timer callbacks. The localId and resetCount must still match the
182
+ // current pending mention so older timers cannot publish after later user edits.
183
+ if (!isAgentMentionsExperimentEnabled || !pendingTypedAgentMention || pendingTypedAgentMention.localId !== (params === null || params === void 0 ? void 0 : params.localId) || pendingTypedAgentMention.resetCount !== (params === null || params === void 0 ? void 0 : params.resetCount)) {
184
+ break;
185
+ }
186
+ var pendingMentionDetails = getAgentMentionDetailsAtPos(newState, pendingTypedAgentMention.pos, function (attrs) {
187
+ return attrs.localId === pendingTypedAgentMention.localId;
188
+ });
189
+ if (!pendingMentionDetails) {
190
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
191
+ pendingTypedAgentMention: null
192
+ });
193
+ break;
194
+ }
195
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
196
+ pendingTypedAgentMention: null,
197
+ lastInsertedAgentMentionId: pendingMentionDetails.id,
198
+ lastInsertedAgentMentionContext: pendingMentionDetails.context,
199
+ lastInsertedAgentMentionParentNodeType: pendingMentionDetails.parentNodeType,
200
+ lastAgentMentionInsertionCount: ((_newPluginState$lastA = newPluginState.lastAgentMentionInsertionCount) !== null && _newPluginState$lastA !== void 0 ? _newPluginState$lastA : 0) + 1
201
+ });
202
+ hasPublicPluginStateChanged = true;
203
+ break;
204
+ }
87
205
  case ACTIONS.SET_PROVIDER:
88
206
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
89
207
  mentionProvider: params.provider
90
208
  });
91
- hasNewPluginState = true;
209
+ hasPublicPluginStateChanged = true;
92
210
  break;
93
211
  }
94
212
 
95
213
  // When the agent mentions experiment is off, dispatch immediately (original behaviour).
96
214
  // When it's on, defer dispatch to after the agent tracking block below so that
97
215
  // agent-mention state changes are included in the notification.
98
- if (hasNewPluginState && !editorExperiment('platform_editor_agent_mentions', true)) {
216
+ if (hasPublicPluginStateChanged && !isAgentMentionsExperimentEnabled) {
99
217
  pmPluginFactoryParams.dispatch(mentionPluginKey, newPluginState);
100
218
  }
219
+ if (isAgentMentionsExperimentEnabled && tr.docChanged && tr.getMeta('replaceDocument')) {
220
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
221
+ pendingTypedAgentMention: null,
222
+ lastInsertedAgentMentionId: null,
223
+ lastInsertedAgentMentionContext: null,
224
+ lastInsertedAgentMentionParentNodeType: null
225
+ });
226
+ hasPublicPluginStateChanged = true;
227
+ }
101
228
  if (options !== null && options !== void 0 && options.handleMentionsChanged && tr.docChanged) {
102
229
  var _insm$session, _insm$session2;
103
230
  (_insm$session = insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('mentionDeletionDetection');
@@ -158,7 +285,7 @@ export function createMentionPlugin(_ref) {
158
285
  (_insm$session2 = insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('mentionDeletionDetection');
159
286
  }
160
287
  var isAIStreaming = Boolean(tr.getMeta(AI_STREAMING_TRANSFORMATION_META_KEY));
161
- if (tr.docChanged && !tr.getMeta('replaceDocument') && !isAIStreaming && editorExperiment('platform_editor_agent_mentions', true)) {
288
+ if (tr.docChanged && !tr.getMeta('replaceDocument') && !isAIStreaming && isAgentMentionsExperimentEnabled) {
162
289
  var _mentionSchema = newState.schema.nodes.mention;
163
290
  var newDocRanges = [];
164
291
  var oldDocRanges = [];
@@ -204,14 +331,16 @@ export function createMentionPlugin(_ref) {
204
331
  oldDocRanges.push.apply(oldDocRanges, stepOldRanges);
205
332
  }
206
333
  });
207
- if (stepsTouchMentions || newPluginState.lastInsertedAgentMentionId) {
208
- var _newPluginState$lastA, _newPluginState$lastI, _newPluginState$lastI2, _newPluginState$lastI3;
334
+ var shouldResolveAgentMentionState = stepsTouchMentions || Boolean(newPluginState.lastInsertedAgentMentionId);
335
+ if (shouldResolveAgentMentionState) {
336
+ var _newPluginState$lastA2, _newPluginState$lastI, _newPluginState$lastI2, _newPluginState$lastI3;
209
337
  var agentMentionId = null;
210
338
  var agentMentionContext = null;
211
339
  var agentMentionParentNodeType = null;
212
340
  var newCount = 0;
213
341
  var oldAgentMentionId = null;
214
342
  var oldCount = 0;
343
+ var pendingTypedAgentMentionDetails = {};
215
344
  if (stepsTouchMentions) {
216
345
  var _iterator = _createForOfIteratorHelper(newDocRanges),
217
346
  _step;
@@ -222,16 +351,26 @@ export function createMentionPlugin(_ref) {
222
351
  to = _step$value[1];
223
352
  var clampedTo = Math.min(to, newState.doc.content.size);
224
353
  if (from >= clampedTo) continue;
225
- newState.doc.nodesBetween(from, clampedTo, function (node, _pos, parent) {
354
+ newState.doc.nodesBetween(from, clampedTo, function (node, pos) {
226
355
  if (node.type !== _mentionSchema || !AGENT_USER_TYPES.has(node.attrs.userType)) {
227
356
  return true;
228
357
  }
229
358
  newCount++;
359
+ if (pendingTypedAgentMentionDetails.current === undefined && action === ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && node.attrs.localId === (params === null || params === void 0 ? void 0 : params.localId)) {
360
+ var _getAgentMentionDetai;
361
+ pendingTypedAgentMentionDetails.current = (_getAgentMentionDetai = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
362
+ return attrs.localId === params.localId;
363
+ })) !== null && _getAgentMentionDetai !== void 0 ? _getAgentMentionDetai : undefined;
364
+ }
230
365
  if (agentMentionId === null && node.attrs.id) {
231
- var _parent$type$name;
232
- agentMentionId = node.attrs.id;
233
- agentMentionParentNodeType = (_parent$type$name = parent === null || parent === void 0 ? void 0 : parent.type.name) !== null && _parent$type$name !== void 0 ? _parent$type$name : null;
234
- agentMentionContext = (parent === null || parent === void 0 ? void 0 : parent.textContent.trim()) || null;
366
+ var agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
367
+ return attrs.id === node.attrs.id;
368
+ });
369
+ if (agentMentionDetails) {
370
+ agentMentionId = agentMentionDetails.id;
371
+ agentMentionContext = agentMentionDetails.context;
372
+ agentMentionParentNodeType = agentMentionDetails.parentNodeType;
373
+ }
235
374
  }
236
375
  return true;
237
376
  });
@@ -271,33 +410,43 @@ export function createMentionPlugin(_ref) {
271
410
  // When a deletion collapses the new-doc range to a zero-width point, or when
272
411
  // the doc changed but no step covered the tracked mention, the new-doc scan
273
412
  // above finds nothing. Check whether any agent mention survived in the document.
274
- var resolvedFromSurvivor = false;
413
+ var resolvedFromFullDocFallback = false;
275
414
  if (agentMentionId === null && newPluginState.lastInsertedAgentMentionId) {
276
- var prevId = newPluginState.lastInsertedAgentMentionId;
277
- var survivorId = null;
278
- var survivorContext = null;
279
- var survivorParentNodeType = null;
280
- newState.doc.descendants(function (node, _pos, parent) {
281
- if (survivorId === prevId) return false;
282
- if (node.type === _mentionSchema && AGENT_USER_TYPES.has(node.attrs.userType)) {
283
- var _parent$type$name2;
284
- // Prefer the previously tracked ID; otherwise keep the first found.
285
- survivorId = node.attrs.id;
286
- survivorParentNodeType = (_parent$type$name2 = parent === null || parent === void 0 ? void 0 : parent.type.name) !== null && _parent$type$name2 !== void 0 ? _parent$type$name2 : null;
287
- survivorContext = (parent === null || parent === void 0 ? void 0 : parent.textContent.trim()) || null;
288
- }
289
- return survivorId !== prevId;
290
- });
291
- if (survivorId !== null) {
292
- agentMentionId = survivorId;
293
- agentMentionContext = survivorContext;
294
- agentMentionParentNodeType = survivorParentNodeType;
295
- resolvedFromSurvivor = true;
415
+ var survivorDetails = getSurvivingAgentMentionDetails(newState, newPluginState.lastInsertedAgentMentionId);
416
+ if (survivorDetails) {
417
+ agentMentionId = survivorDetails.id;
418
+ agentMentionContext = survivorDetails.context;
419
+ agentMentionParentNodeType = survivorDetails.parentNodeType;
420
+ resolvedFromFullDocFallback = true;
296
421
  }
297
422
  }
298
- var isNewInsertion = agentMentionId !== null && !resolvedFromSurvivor && (oldAgentMentionId !== agentMentionId || newCount > oldCount);
299
- var newInsertionCount = isNewInsertion ? ((_newPluginState$lastA = newPluginState.lastAgentMentionInsertionCount) !== null && _newPluginState$lastA !== void 0 ? _newPluginState$lastA : 0) + 1 : undefined;
300
- if (agentMentionId !== ((_newPluginState$lastI = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI !== void 0 ? _newPluginState$lastI : null) || agentMentionContext !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionContext) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || newInsertionCount !== undefined) {
423
+ var isNewInsertion = agentMentionId !== null && !resolvedFromFullDocFallback && (oldAgentMentionId !== agentMentionId || newCount > oldCount);
424
+ var isPendingTypedAgentMentionInsertion = isNewInsertion && action === ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && typeof (params === null || params === void 0 ? void 0 : params.localId) === 'string';
425
+ var newInsertionCount = isNewInsertion ? ((_newPluginState$lastA2 = newPluginState.lastAgentMentionInsertionCount) !== null && _newPluginState$lastA2 !== void 0 ? _newPluginState$lastA2 : 0) + 1 : undefined;
426
+ if (isPendingTypedAgentMentionInsertion && pendingTypedAgentMentionDetails.current) {
427
+ var pendingTypedAgentMentionLocalId = params === null || params === void 0 ? void 0 : params.localId;
428
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
429
+ pendingTypedAgentMention: {
430
+ id: pendingTypedAgentMentionDetails.current.id,
431
+ localId: pendingTypedAgentMentionLocalId,
432
+ nodeSize: pendingTypedAgentMentionDetails.current.nodeSize,
433
+ pos: pendingTypedAgentMentionDetails.current.pos,
434
+ resetCount: 1
435
+ }
436
+ });
437
+ } else if (isPendingTypedAgentMentionInsertion) {
438
+ // Fallback: if the localId-specific scan missed the typed mention,
439
+ // publish immediately so the insertion is not dropped.
440
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
441
+ pendingTypedAgentMention: null,
442
+ lastInsertedAgentMentionId: agentMentionId,
443
+ lastInsertedAgentMentionContext: agentMentionContext,
444
+ lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
445
+ }, newInsertionCount !== undefined ? {
446
+ lastAgentMentionInsertionCount: newInsertionCount
447
+ } : {});
448
+ hasPublicPluginStateChanged = true;
449
+ } else if (agentMentionId !== ((_newPluginState$lastI = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI !== void 0 ? _newPluginState$lastI : null) || agentMentionContext !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionContext) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || newInsertionCount !== undefined) {
301
450
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
302
451
  lastInsertedAgentMentionId: agentMentionId,
303
452
  lastInsertedAgentMentionContext: agentMentionContext,
@@ -305,11 +454,18 @@ export function createMentionPlugin(_ref) {
305
454
  }, newInsertionCount !== undefined ? {
306
455
  lastAgentMentionInsertionCount: newInsertionCount
307
456
  } : {});
308
- hasNewPluginState = true;
457
+ hasPublicPluginStateChanged = true;
309
458
  }
310
459
  }
311
460
  }
312
- if (hasNewPluginState && editorExperiment('platform_editor_agent_mentions', true)) {
461
+ if (isAgentMentionsExperimentEnabled && newPluginState.pendingTypedAgentMention && action !== ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && action !== ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION && tr.docChanged) {
462
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
463
+ pendingTypedAgentMention: getPendingTypedAgentMentionAfterDocChange(newState, tr, newPluginState.pendingTypedAgentMention, {
464
+ resetTimer: isQualifyingLocalUserDocChange(tr)
465
+ })
466
+ });
467
+ }
468
+ if (hasPublicPluginStateChanged && isAgentMentionsExperimentEnabled) {
313
469
  pmPluginFactoryParams.dispatch(mentionPluginKey, newPluginState);
314
470
  }
315
471
  return newPluginState;
@@ -327,6 +483,47 @@ export function createMentionPlugin(_ref) {
327
483
  }
328
484
  },
329
485
  view: function view(editorView) {
486
+ var isAgentMentionsEnabled = editorExperiment('platform_editor_agent_mentions', true);
487
+ var pendingTypedAgentMentionTimer;
488
+ var pendingTypedAgentMentionTimerKey = null;
489
+ var clearPendingTypedAgentMentionTimer = function clearPendingTypedAgentMentionTimer() {
490
+ if (pendingTypedAgentMentionTimer) {
491
+ clearTimeout(pendingTypedAgentMentionTimer);
492
+ pendingTypedAgentMentionTimer = undefined;
493
+ }
494
+ pendingTypedAgentMentionTimerKey = null;
495
+ };
496
+ var schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
497
+ if (!isAgentMentionsEnabled) {
498
+ clearPendingTypedAgentMentionTimer();
499
+ return;
500
+ }
501
+ var pendingTypedAgentMention = mentionPluginState === null || mentionPluginState === void 0 ? void 0 : mentionPluginState.pendingTypedAgentMention;
502
+ if (!pendingTypedAgentMention) {
503
+ clearPendingTypedAgentMentionTimer();
504
+ return;
505
+ }
506
+ var timerKey = "".concat(pendingTypedAgentMention.localId, ":").concat(pendingTypedAgentMention.resetCount);
507
+ if (timerKey === pendingTypedAgentMentionTimerKey) {
508
+ return;
509
+ }
510
+ clearPendingTypedAgentMentionTimer();
511
+ pendingTypedAgentMentionTimerKey = timerKey;
512
+ pendingTypedAgentMentionTimer = setTimeout(function () {
513
+ var _mentionPluginKey$get;
514
+ var latestPendingTypedAgentMention = (_mentionPluginKey$get = mentionPluginKey.getState(editorView.state)) === null || _mentionPluginKey$get === void 0 ? void 0 : _mentionPluginKey$get.pendingTypedAgentMention;
515
+ if (!latestPendingTypedAgentMention || latestPendingTypedAgentMention.localId !== pendingTypedAgentMention.localId || latestPendingTypedAgentMention.resetCount !== pendingTypedAgentMention.resetCount) {
516
+ return;
517
+ }
518
+ editorView.dispatch(editorView.state.tr.setMeta(mentionPluginKey, {
519
+ action: ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION,
520
+ params: {
521
+ localId: pendingTypedAgentMention.localId,
522
+ resetCount: pendingTypedAgentMention.resetCount
523
+ }
524
+ }));
525
+ }, AGENT_MENTION_INACTIVITY_MS);
526
+ };
330
527
  var providerHandler = function providerHandler(name, providerPromise) {
331
528
  switch (name) {
332
529
  case 'mentionProvider':
@@ -372,7 +569,15 @@ export function createMentionPlugin(_ref) {
372
569
  pmPluginFactoryParams.providerFactory.subscribe('mentionProvider', providerHandler);
373
570
  }
374
571
  return {
572
+ update: function update(view, prevState) {
573
+ var mentionPluginState = mentionPluginKey.getState(view.state);
574
+ if (mentionPluginState === mentionPluginKey.getState(prevState)) {
575
+ return;
576
+ }
577
+ schedulePendingTypedAgentMentionTimer(mentionPluginState);
578
+ },
375
579
  destroy: function destroy() {
580
+ clearPendingTypedAgentMentionTimer();
376
581
  if (pmPluginFactoryParams.providerFactory) {
377
582
  pmPluginFactoryParams.providerFactory.unsubscribe('mentionProvider', providerHandler);
378
583
  }
@@ -98,7 +98,7 @@ export var buildTypeAheadInviteItemClickedPayload = function buildTypeAheadInvit
98
98
  }, additionalAttributes)
99
99
  };
100
100
  };
101
- export var buildTypeAheadInsertedPayload = function buildTypeAheadInsertedPayload(duration, upKeyCount, downKeyCount, sessionId, insertType, mention, mentionLocalId, mentionList, query, contextIdentifierProvider, taskListId, taskItemId) {
101
+ export var buildTypeAheadInsertedPayload = function buildTypeAheadInsertedPayload(duration, upKeyCount, downKeyCount, sessionId, insertType, mention, mentionLocalId, mentionList, query, contextIdentifierProvider, taskListId, taskItemId, isAgent) {
102
102
  var _extractAttributesFro3 = extractAttributesFromQuery(query),
103
103
  queryLength = _extractAttributesFro3.queryLength,
104
104
  spaceInQuery = _extractAttributesFro3.spaceInQuery;
@@ -117,7 +117,7 @@ export var buildTypeAheadInsertedPayload = function buildTypeAheadInsertedPayloa
117
117
  containerId: containerId,
118
118
  objectId: objectId,
119
119
  childObjectId: childObjectId,
120
- attributes: {
120
+ attributes: _objectSpread(_objectSpread({
121
121
  sessionId: sessionId,
122
122
  duration: duration,
123
123
  position: getPosition(mentionList, mention),
@@ -132,14 +132,17 @@ export var buildTypeAheadInsertedPayload = function buildTypeAheadInsertedPayloa
132
132
  upKeyCount: upKeyCount,
133
133
  downKeyCount: downKeyCount,
134
134
  memberCount: isTeamType(mention.userType) && mention.context ? mention.context.memberCount : null,
135
- includesYou: isTeamType(mention.userType) && mention.context ? mention.context.includesYou : null,
135
+ includesYou: isTeamType(mention.userType) && mention.context ? mention.context.includesYou : null
136
+ }, isAgent ? {
137
+ isAgent: isAgent
138
+ } : {}), {}, {
136
139
  taskListId: taskListId,
137
140
  taskItemId: taskItemId,
138
141
  localId: mentionLocalId,
139
142
  containerId: containerId,
140
143
  objectId: objectId,
141
144
  childObjectId: childObjectId
142
- }
145
+ })
143
146
  };
144
147
  };
145
148
  export var buildTypeAheadRenderedPayload = function buildTypeAheadRenderedPayload(duration, userIds, query, teams, xProductMentionsLength) {