@atlaskit/editor-plugin-metrics 3.2.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-metrics
2
2
 
3
+ ## 3.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#114961](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/114961)
8
+ [`f31ba30a89a05`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/f31ba30a89a05) -
9
+ ED-26301 Add logic to exclude transactions that shouldn't increment totalActionCount
10
+
3
11
  ## 3.2.0
4
12
 
5
13
  ### Minor Changes
@@ -78,14 +78,13 @@ var metricsPlugin = exports.metricsPlugin = function metricsPlugin(_ref) {
78
78
  });
79
79
  }
80
80
  }
81
- var newTr = tr;
82
- newTr.setMeta(_main.metricsKey, {
81
+ tr.setMeta(_main.metricsKey, {
83
82
  intentToStartEditTime: performance.now(),
84
83
  shouldStartTimer: shouldStartTimer,
85
84
  newSelection: newSelection,
86
85
  shouldPersistActiveSession: shouldPersistActiveSession
87
86
  });
88
- return newTr;
87
+ return tr;
89
88
  };
90
89
  }
91
90
  },
@@ -7,12 +7,12 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.metricsKey = exports.initialPluginState = exports.createPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _bindEventListener = require("bind-event-listener");
10
- var _steps = require("@atlaskit/adf-schema/steps");
11
10
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
12
- var _utils = require("@atlaskit/editor-common/utils");
13
11
  var _state = require("@atlaskit/editor-prosemirror/state");
12
+ var _transform = require("@atlaskit/editor-prosemirror/transform");
14
13
  var _activeSessionTimer = require("./utils/active-session-timer");
15
14
  var _analytics = require("./utils/analytics");
15
+ var _checkTrActionType = require("./utils/check-tr-action-type");
16
16
  var _isNonTextUndo = require("./utils/is-non-text-undo");
17
17
  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; }
18
18
  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; }
@@ -46,7 +46,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
46
46
  },
47
47
  // eslint-disable-next-line @typescript-eslint/max-params
48
48
  apply: function apply(tr, pluginState, oldState, newState) {
49
- var _meta$shouldPersistAc;
49
+ var _meta$shouldPersistAc, _tr$steps;
50
50
  if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
51
51
  return pluginState;
52
52
  }
@@ -59,20 +59,16 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
59
59
  });
60
60
  }
61
61
  var shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
62
- var canIgnoreTr = function canIgnoreTr() {
63
- return !tr.steps.every(function (e) {
64
- return e instanceof _steps.AnalyticsStep;
65
- });
66
- };
67
- var docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
62
+ var hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(function (step) {
63
+ return step instanceof _transform.ReplaceStep || step instanceof _transform.ReplaceAroundStep || step instanceof _transform.AddMarkStep;
64
+ }));
68
65
  var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
69
66
  var now = performance.now();
70
- if (!intentToStartEditTime) {
71
- if (docChangedWithoutAnalytics || tr.storedMarksSet) {
72
- intentToStartEditTime = now;
73
- } else {
74
- return _objectSpread({}, pluginState);
75
- }
67
+ if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
68
+ return pluginState;
69
+ }
70
+ if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
71
+ intentToStartEditTime = now;
76
72
  }
77
73
 
78
74
  // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
@@ -87,32 +83,55 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
87
83
  }) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
88
84
  undoCount: undoCount
89
85
  });
90
- if (docChangedWithoutAnalytics) {
86
+ if (hasDocChanges) {
91
87
  timer.startTimer();
92
88
  var actionTypeCount = pluginState.actionTypeCount,
93
89
  timeOfLastTextInput = pluginState.timeOfLastTextInput,
94
90
  totalActionCount = pluginState.totalActionCount,
95
- activeSessionTime = pluginState.activeSessionTime;
96
- // If previous and current action is text insertion, then don't increase total action count
97
- var isActionTextInput = (0, _utils.isTextInput)(tr);
98
- var newActiveSessionTime = activeSessionTime + (now - intentToStartEditTime);
99
- var newTextInputCount = isActionTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
100
- var newTotalActionCount = pluginState.totalActionCount + 1;
101
- if (pluginState.timeOfLastTextInput && isActionTextInput) {
102
- newActiveSessionTime = activeSessionTime + (now - (timeOfLastTextInput || 0));
103
- newTextInputCount = actionTypeCount.textInputCount;
91
+ previousTrType = pluginState.previousTrType;
92
+ if ((0, _checkTrActionType.shouldSkipTr)(tr)) {
93
+ return pluginState;
94
+ }
95
+ var trType = (0, _checkTrActionType.checkTrActionType)(tr);
96
+ var shouldNotIncrementActionCount = false;
97
+ var shouldSetTimeOfLastTextInput = false;
98
+ var isTextInput = false;
99
+ if (trType) {
100
+ var _trType$extraData, _previousTrType$extra;
101
+ var isNotNewStatus = trType.type === _checkTrActionType.ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === _checkTrActionType.ActionType.UPDATING_STATUS && (trType === null || trType === void 0 || (_trType$extraData = trType.extraData) === null || _trType$extraData === void 0 ? void 0 : _trType$extraData.statusId) === (previousTrType === null || previousTrType === void 0 || (_previousTrType$extra = previousTrType.extraData) === null || _previousTrType$extra === void 0 ? void 0 : _previousTrType$extra.statusId);
102
+ var isAddingTextToListNode = trType.type === _checkTrActionType.ActionType.TEXT_INPUT && !!previousTrType && [_checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
103
+ var isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === _checkTrActionType.ActionType.TEXT_INPUT && [_checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
104
+
105
+ // Check if tr is textInput and only increment textInputCount if previous action was not textInput
106
+ isTextInput = [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
107
+
108
+ // timeOfLastTextInput should be set if tr includes continuous text input on the same node
109
+ shouldSetTimeOfLastTextInput = [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED, _checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE, _checkTrActionType.ActionType.UPDATING_STATUS].includes(trType.type) || isNotNewStatus;
110
+
111
+ // Should not increase action count if tr is text input,
112
+ // empty line added or deleted, updating new list item or is updating same status node
113
+
114
+ shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
115
+ }
116
+ var newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
117
+ var newTotalActionCount = totalActionCount + 1;
118
+ if (timeOfLastTextInput && shouldNotIncrementActionCount) {
104
119
  newTotalActionCount = totalActionCount;
105
120
  }
121
+ if (timeOfLastTextInput && isTextInput && previousTrType && [_checkTrActionType.ActionType.TEXT_INPUT, _checkTrActionType.ActionType.EMPTY_LINE_ADDED_OR_DELETED, _checkTrActionType.ActionType.UPDATING_NEW_LIST_TYPE_ITEM, _checkTrActionType.ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type)) {
122
+ newTextInputCount = actionTypeCount.textInputCount;
123
+ }
106
124
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
107
- activeSessionTime: newActiveSessionTime,
125
+ activeSessionTime: now - intentToStartEditTime,
108
126
  totalActionCount: newTotalActionCount,
109
- timeOfLastTextInput: isActionTextInput ? now : undefined,
127
+ timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
110
128
  contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
111
129
  actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
112
130
  textInputCount: newTextInputCount
113
131
  }),
114
132
  intentToStartEditTime: intentToStartEditTime,
115
- shouldPersistActiveSession: shouldPersistActiveSession
133
+ shouldPersistActiveSession: shouldPersistActiveSession,
134
+ previousTrType: trType
116
135
  });
117
136
  return newPluginState;
118
137
  }
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.shouldSkipTr = exports.checkTrActionType = exports.ActionType = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _steps = require("@atlaskit/adf-schema/steps");
10
+ var _transform = require("@atlaskit/editor-prosemirror/transform");
11
+ var ActionType = exports.ActionType = /*#__PURE__*/function (ActionType) {
12
+ ActionType["TEXT_INPUT"] = "textInput";
13
+ ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
14
+ ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
15
+ ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
16
+ ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
17
+ ActionType["ADDING_LINK"] = "addingLink";
18
+ ActionType["UPDATING_STATUS"] = "updatingStatus";
19
+ return ActionType;
20
+ }({});
21
+ var isTextInput = function isTextInput(step) {
22
+ var _ref = step,
23
+ content = _ref.slice.content,
24
+ from = _ref.from,
25
+ to = _ref.to;
26
+ var node = content.firstChild;
27
+ var isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
28
+ var isDeletingCharacter = to - from === 1 && content.childCount === 0;
29
+ return isAddingCharacter || isDeletingCharacter;
30
+ };
31
+ var isEmptyLineAddedOrDeleted = function isEmptyLineAddedOrDeleted(step) {
32
+ var _ref2 = step,
33
+ content = _ref2.slice.content,
34
+ from = _ref2.from,
35
+ to = _ref2.to;
36
+ var isEmptyLineDeleted = to - from === 2 && content.size === 0;
37
+ if (isEmptyLineDeleted) {
38
+ return true;
39
+ }
40
+ var isEmptyLineAdded = false;
41
+ content.forEach(function (node) {
42
+ isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
43
+ });
44
+ return isEmptyLineAdded;
45
+ };
46
+ var isUpdatingListTypeNode = function isUpdatingListTypeNode(step) {
47
+ var slice = step.slice;
48
+ var childCount = slice.content.childCount;
49
+ if (childCount < 1) {
50
+ return false;
51
+ }
52
+ var isListTypeNode = false;
53
+ slice.content.forEach(function (node) {
54
+ isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
55
+ });
56
+ if (!isListTypeNode) {
57
+ return false;
58
+ }
59
+ return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
60
+ };
61
+ var isUpdatingStatus = function isUpdatingStatus(step) {
62
+ var slice = step.slice;
63
+ var firstChild = slice.content.firstChild;
64
+ if (!firstChild) {
65
+ return undefined;
66
+ }
67
+ return firstChild.type.name === 'status' && firstChild.attrs.localId;
68
+ };
69
+ var isAddingLink = function isAddingLink(tr) {
70
+ var hasLinkStep = tr.steps.some(function (step) {
71
+ return step instanceof _steps.LinkMetaStep;
72
+ });
73
+ var hasReplaceStep = tr.steps.some(function (step) {
74
+ return step instanceof _transform.ReplaceStep;
75
+ });
76
+ return hasLinkStep && !hasReplaceStep;
77
+ };
78
+ var isTypeAheadRelatedTr = function isTypeAheadRelatedTr(tr) {
79
+ var _tr$getMeta;
80
+ if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
81
+ return 'INSERT_RAW_QUERY';
82
+ }
83
+ if (!tr.getMeta('appendedTransaction')) {
84
+ return false;
85
+ }
86
+ var insertTypeAheadStep = tr.steps.find(function (step) {
87
+ return step instanceof _steps.InsertTypeAheadStep;
88
+ });
89
+ var replaceStep = tr.steps.find(function (step) {
90
+ return step instanceof _transform.ReplaceStep;
91
+ });
92
+ if (!insertTypeAheadStep || !replaceStep) {
93
+ return false;
94
+ }
95
+ return insertTypeAheadStep instanceof _steps.InsertTypeAheadStep && insertTypeAheadStep.stage;
96
+ };
97
+ var shouldSkipTr = exports.shouldSkipTr = function shouldSkipTr(tr) {
98
+ var resolvingLink = isAddingLink(tr);
99
+ if (resolvingLink) {
100
+ return true;
101
+ }
102
+ var typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
103
+ if (typeAheadRelatedTr) {
104
+ return typeAheadRelatedTr !== 'INSERTING_ITEM';
105
+ } else {
106
+ return tr.getMeta('appendedTransaction');
107
+ }
108
+ };
109
+ var checkTrActionType = exports.checkTrActionType = function checkTrActionType(tr) {
110
+ if (tr.getMeta('input_rule_plugin_transaction')) {
111
+ return {
112
+ type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
113
+ };
114
+ }
115
+ var stepsLength = tr.steps.length;
116
+ if (stepsLength <= 0) {
117
+ return undefined;
118
+ }
119
+ if (isAddingLink(tr)) {
120
+ return {
121
+ type: ActionType.ADDING_LINK
122
+ };
123
+ }
124
+ var _tr$steps = (0, _slicedToArray2.default)(tr.steps, 1),
125
+ firstStep = _tr$steps[0];
126
+ var isReplaceStep = firstStep instanceof _transform.ReplaceStep;
127
+ var isReplaceAroundStep = firstStep instanceof _transform.ReplaceAroundStep;
128
+ if (!isReplaceStep && !isReplaceAroundStep) {
129
+ return undefined;
130
+ }
131
+ if (isReplaceStep) {
132
+ if (isTextInput(firstStep)) {
133
+ return {
134
+ type: ActionType.TEXT_INPUT
135
+ };
136
+ }
137
+ if (isEmptyLineAddedOrDeleted(firstStep)) {
138
+ return {
139
+ type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
140
+ };
141
+ }
142
+ var statusId = isUpdatingStatus(firstStep);
143
+ if (statusId) {
144
+ return {
145
+ type: ActionType.UPDATING_STATUS,
146
+ extraData: {
147
+ statusId: statusId
148
+ }
149
+ };
150
+ }
151
+ }
152
+ var updatingListTypeNode = isUpdatingListTypeNode(firstStep);
153
+ if (updatingListTypeNode) {
154
+ return {
155
+ type: updatingListTypeNode
156
+ };
157
+ }
158
+ return undefined;
159
+ };
@@ -68,14 +68,13 @@ export const metricsPlugin = ({
68
68
  });
69
69
  }
70
70
  }
71
- const newTr = tr;
72
- newTr.setMeta(metricsKey, {
71
+ tr.setMeta(metricsKey, {
73
72
  intentToStartEditTime: performance.now(),
74
73
  shouldStartTimer,
75
74
  newSelection,
76
75
  shouldPersistActiveSession
77
76
  });
78
- return newTr;
77
+ return tr;
79
78
  }
80
79
  },
81
80
  getSharedState(editorState) {
@@ -1,10 +1,10 @@
1
1
  import { bind } from 'bind-event-listener';
2
- import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
3
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
- import { isTextInput } from '@atlaskit/editor-common/utils';
5
3
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
+ import { AddMarkStep, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
6
5
  import { ActiveSessionTimer } from './utils/active-session-timer';
7
6
  import { getAnalyticsPayload } from './utils/analytics';
7
+ import { ActionType, checkTrActionType, shouldSkipTr } from './utils/check-tr-action-type';
8
8
  import { isNonTextUndo } from './utils/is-non-text-undo';
9
9
  export const metricsKey = new PluginKey('metricsPlugin');
10
10
  export const initialPluginState = {
@@ -37,7 +37,7 @@ export const createPlugin = api => {
37
37
  },
38
38
  // eslint-disable-next-line @typescript-eslint/max-params
39
39
  apply(tr, pluginState, oldState, newState) {
40
- var _meta$shouldPersistAc;
40
+ var _meta$shouldPersistAc, _tr$steps;
41
41
  if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
42
42
  return pluginState;
43
43
  }
@@ -51,18 +51,14 @@ export const createPlugin = api => {
51
51
  };
52
52
  }
53
53
  const shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
54
- const canIgnoreTr = () => !tr.steps.every(e => e instanceof AnalyticsStep);
55
- const docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
54
+ const hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(step => step instanceof ReplaceStep || step instanceof ReplaceAroundStep || step instanceof AddMarkStep));
56
55
  let intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
57
56
  const now = performance.now();
58
- if (!intentToStartEditTime) {
59
- if (docChangedWithoutAnalytics || tr.storedMarksSet) {
60
- intentToStartEditTime = now;
61
- } else {
62
- return {
63
- ...pluginState
64
- };
65
- }
57
+ if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
58
+ return pluginState;
59
+ }
60
+ if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
61
+ intentToStartEditTime = now;
66
62
  }
67
63
 
68
64
  // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
@@ -79,36 +75,59 @@ export const createPlugin = api => {
79
75
  ...initialPluginState.actionTypeCount,
80
76
  undoCount
81
77
  };
82
- if (docChangedWithoutAnalytics) {
78
+ if (hasDocChanges) {
83
79
  timer.startTimer();
84
80
  const {
85
81
  actionTypeCount,
86
82
  timeOfLastTextInput,
87
83
  totalActionCount,
88
- activeSessionTime
84
+ previousTrType
89
85
  } = pluginState;
90
- // If previous and current action is text insertion, then don't increase total action count
91
- const isActionTextInput = isTextInput(tr);
92
- let newActiveSessionTime = activeSessionTime + (now - intentToStartEditTime);
93
- let newTextInputCount = isActionTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
94
- let newTotalActionCount = pluginState.totalActionCount + 1;
95
- if (pluginState.timeOfLastTextInput && isActionTextInput) {
96
- newActiveSessionTime = activeSessionTime + (now - (timeOfLastTextInput || 0));
97
- newTextInputCount = actionTypeCount.textInputCount;
86
+ if (shouldSkipTr(tr)) {
87
+ return pluginState;
88
+ }
89
+ const trType = checkTrActionType(tr);
90
+ let shouldNotIncrementActionCount = false;
91
+ let shouldSetTimeOfLastTextInput = false;
92
+ let isTextInput = false;
93
+ if (trType) {
94
+ var _trType$extraData, _previousTrType$extra;
95
+ const isNotNewStatus = trType.type === ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === ActionType.UPDATING_STATUS && (trType === null || trType === void 0 ? void 0 : (_trType$extraData = trType.extraData) === null || _trType$extraData === void 0 ? void 0 : _trType$extraData.statusId) === (previousTrType === null || previousTrType === void 0 ? void 0 : (_previousTrType$extra = previousTrType.extraData) === null || _previousTrType$extra === void 0 ? void 0 : _previousTrType$extra.statusId);
96
+ const isAddingTextToListNode = trType.type === ActionType.TEXT_INPUT && !!previousTrType && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
97
+ const isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === ActionType.TEXT_INPUT && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
98
+
99
+ // Check if tr is textInput and only increment textInputCount if previous action was not textInput
100
+ isTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
101
+
102
+ // timeOfLastTextInput should be set if tr includes continuous text input on the same node
103
+ shouldSetTimeOfLastTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE, ActionType.UPDATING_STATUS].includes(trType.type) || isNotNewStatus;
104
+
105
+ // Should not increase action count if tr is text input,
106
+ // empty line added or deleted, updating new list item or is updating same status node
107
+
108
+ shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
109
+ }
110
+ let newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
111
+ let newTotalActionCount = totalActionCount + 1;
112
+ if (timeOfLastTextInput && shouldNotIncrementActionCount) {
98
113
  newTotalActionCount = totalActionCount;
99
114
  }
115
+ if (timeOfLastTextInput && isTextInput && previousTrType && [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type)) {
116
+ newTextInputCount = actionTypeCount.textInputCount;
117
+ }
100
118
  const newPluginState = {
101
119
  ...pluginState,
102
- activeSessionTime: newActiveSessionTime,
120
+ activeSessionTime: now - intentToStartEditTime,
103
121
  totalActionCount: newTotalActionCount,
104
- timeOfLastTextInput: isActionTextInput ? now : undefined,
122
+ timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
105
123
  contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
106
124
  actionTypeCount: {
107
125
  ...newActionTypeCount,
108
126
  textInputCount: newTextInputCount
109
127
  },
110
128
  intentToStartEditTime,
111
- shouldPersistActiveSession
129
+ shouldPersistActiveSession,
130
+ previousTrType: trType
112
131
  };
113
132
  return newPluginState;
114
133
  }
@@ -0,0 +1,152 @@
1
+ import { InsertTypeAheadStep, LinkMetaStep } from '@atlaskit/adf-schema/steps';
2
+ import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
3
+ export let ActionType = /*#__PURE__*/function (ActionType) {
4
+ ActionType["TEXT_INPUT"] = "textInput";
5
+ ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
6
+ ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
7
+ ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
8
+ ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
9
+ ActionType["ADDING_LINK"] = "addingLink";
10
+ ActionType["UPDATING_STATUS"] = "updatingStatus";
11
+ return ActionType;
12
+ }({});
13
+ const isTextInput = step => {
14
+ const {
15
+ slice: {
16
+ content
17
+ },
18
+ from,
19
+ to
20
+ } = step;
21
+ const node = content.firstChild;
22
+ const isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
23
+ const isDeletingCharacter = to - from === 1 && content.childCount === 0;
24
+ return isAddingCharacter || isDeletingCharacter;
25
+ };
26
+ const isEmptyLineAddedOrDeleted = step => {
27
+ const {
28
+ slice: {
29
+ content
30
+ },
31
+ from,
32
+ to
33
+ } = step;
34
+ const isEmptyLineDeleted = to - from === 2 && content.size === 0;
35
+ if (isEmptyLineDeleted) {
36
+ return true;
37
+ }
38
+ let isEmptyLineAdded = false;
39
+ content.forEach(node => {
40
+ isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
41
+ });
42
+ return isEmptyLineAdded;
43
+ };
44
+ const isUpdatingListTypeNode = step => {
45
+ const {
46
+ slice
47
+ } = step;
48
+ const childCount = slice.content.childCount;
49
+ if (childCount < 1) {
50
+ return false;
51
+ }
52
+ let isListTypeNode = false;
53
+ slice.content.forEach(node => {
54
+ isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
55
+ });
56
+ if (!isListTypeNode) {
57
+ return false;
58
+ }
59
+ return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
60
+ };
61
+ const isUpdatingStatus = step => {
62
+ const {
63
+ slice
64
+ } = step;
65
+ const firstChild = slice.content.firstChild;
66
+ if (!firstChild) {
67
+ return undefined;
68
+ }
69
+ return firstChild.type.name === 'status' && firstChild.attrs.localId;
70
+ };
71
+ const isAddingLink = tr => {
72
+ const hasLinkStep = tr.steps.some(step => step instanceof LinkMetaStep);
73
+ const hasReplaceStep = tr.steps.some(step => step instanceof ReplaceStep);
74
+ return hasLinkStep && !hasReplaceStep;
75
+ };
76
+ const isTypeAheadRelatedTr = tr => {
77
+ var _tr$getMeta;
78
+ if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
79
+ return 'INSERT_RAW_QUERY';
80
+ }
81
+ if (!tr.getMeta('appendedTransaction')) {
82
+ return false;
83
+ }
84
+ const insertTypeAheadStep = tr.steps.find(step => step instanceof InsertTypeAheadStep);
85
+ const replaceStep = tr.steps.find(step => step instanceof ReplaceStep);
86
+ if (!insertTypeAheadStep || !replaceStep) {
87
+ return false;
88
+ }
89
+ return insertTypeAheadStep instanceof InsertTypeAheadStep && insertTypeAheadStep.stage;
90
+ };
91
+ export const shouldSkipTr = tr => {
92
+ const resolvingLink = isAddingLink(tr);
93
+ if (resolvingLink) {
94
+ return true;
95
+ }
96
+ const typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
97
+ if (typeAheadRelatedTr) {
98
+ return typeAheadRelatedTr !== 'INSERTING_ITEM';
99
+ } else {
100
+ return tr.getMeta('appendedTransaction');
101
+ }
102
+ };
103
+ export const checkTrActionType = tr => {
104
+ if (tr.getMeta('input_rule_plugin_transaction')) {
105
+ return {
106
+ type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
107
+ };
108
+ }
109
+ const stepsLength = tr.steps.length;
110
+ if (stepsLength <= 0) {
111
+ return undefined;
112
+ }
113
+ if (isAddingLink(tr)) {
114
+ return {
115
+ type: ActionType.ADDING_LINK
116
+ };
117
+ }
118
+ const [firstStep] = tr.steps;
119
+ const isReplaceStep = firstStep instanceof ReplaceStep;
120
+ const isReplaceAroundStep = firstStep instanceof ReplaceAroundStep;
121
+ if (!isReplaceStep && !isReplaceAroundStep) {
122
+ return undefined;
123
+ }
124
+ if (isReplaceStep) {
125
+ if (isTextInput(firstStep)) {
126
+ return {
127
+ type: ActionType.TEXT_INPUT
128
+ };
129
+ }
130
+ if (isEmptyLineAddedOrDeleted(firstStep)) {
131
+ return {
132
+ type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
133
+ };
134
+ }
135
+ const statusId = isUpdatingStatus(firstStep);
136
+ if (statusId) {
137
+ return {
138
+ type: ActionType.UPDATING_STATUS,
139
+ extraData: {
140
+ statusId
141
+ }
142
+ };
143
+ }
144
+ }
145
+ const updatingListTypeNode = isUpdatingListTypeNode(firstStep);
146
+ if (updatingListTypeNode) {
147
+ return {
148
+ type: updatingListTypeNode
149
+ };
150
+ }
151
+ return undefined;
152
+ };
@@ -72,14 +72,13 @@ export var metricsPlugin = function metricsPlugin(_ref) {
72
72
  });
73
73
  }
74
74
  }
75
- var newTr = tr;
76
- newTr.setMeta(metricsKey, {
75
+ tr.setMeta(metricsKey, {
77
76
  intentToStartEditTime: performance.now(),
78
77
  shouldStartTimer: shouldStartTimer,
79
78
  newSelection: newSelection,
80
79
  shouldPersistActiveSession: shouldPersistActiveSession
81
80
  });
82
- return newTr;
81
+ return tr;
83
82
  };
84
83
  }
85
84
  },
@@ -2,12 +2,12 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
3
3
  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; }
4
4
  import { bind } from 'bind-event-listener';
5
- import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
6
5
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
- import { isTextInput } from '@atlaskit/editor-common/utils';
8
6
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
7
+ import { AddMarkStep, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
9
8
  import { ActiveSessionTimer } from './utils/active-session-timer';
10
9
  import { getAnalyticsPayload } from './utils/analytics';
10
+ import { ActionType, checkTrActionType, shouldSkipTr } from './utils/check-tr-action-type';
11
11
  import { isNonTextUndo } from './utils/is-non-text-undo';
12
12
  export var metricsKey = new PluginKey('metricsPlugin');
13
13
  export var initialPluginState = {
@@ -39,7 +39,7 @@ export var createPlugin = function createPlugin(api) {
39
39
  },
40
40
  // eslint-disable-next-line @typescript-eslint/max-params
41
41
  apply: function apply(tr, pluginState, oldState, newState) {
42
- var _meta$shouldPersistAc;
42
+ var _meta$shouldPersistAc, _tr$steps;
43
43
  if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
44
44
  return pluginState;
45
45
  }
@@ -52,20 +52,16 @@ export var createPlugin = function createPlugin(api) {
52
52
  });
53
53
  }
54
54
  var shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
55
- var canIgnoreTr = function canIgnoreTr() {
56
- return !tr.steps.every(function (e) {
57
- return e instanceof AnalyticsStep;
58
- });
59
- };
60
- var docChangedWithoutAnalytics = tr.docChanged && canIgnoreTr();
55
+ var hasDocChanges = tr.steps.length > 0 && ((_tr$steps = tr.steps) === null || _tr$steps === void 0 ? void 0 : _tr$steps.some(function (step) {
56
+ return step instanceof ReplaceStep || step instanceof ReplaceAroundStep || step instanceof AddMarkStep;
57
+ }));
61
58
  var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
62
59
  var now = performance.now();
63
- if (!intentToStartEditTime) {
64
- if (docChangedWithoutAnalytics || tr.storedMarksSet) {
65
- intentToStartEditTime = now;
66
- } else {
67
- return _objectSpread({}, pluginState);
68
- }
60
+ if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
61
+ return pluginState;
62
+ }
63
+ if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
64
+ intentToStartEditTime = now;
69
65
  }
70
66
 
71
67
  // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
@@ -80,32 +76,55 @@ export var createPlugin = function createPlugin(api) {
80
76
  }) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
81
77
  undoCount: undoCount
82
78
  });
83
- if (docChangedWithoutAnalytics) {
79
+ if (hasDocChanges) {
84
80
  timer.startTimer();
85
81
  var actionTypeCount = pluginState.actionTypeCount,
86
82
  timeOfLastTextInput = pluginState.timeOfLastTextInput,
87
83
  totalActionCount = pluginState.totalActionCount,
88
- activeSessionTime = pluginState.activeSessionTime;
89
- // If previous and current action is text insertion, then don't increase total action count
90
- var isActionTextInput = isTextInput(tr);
91
- var newActiveSessionTime = activeSessionTime + (now - intentToStartEditTime);
92
- var newTextInputCount = isActionTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
93
- var newTotalActionCount = pluginState.totalActionCount + 1;
94
- if (pluginState.timeOfLastTextInput && isActionTextInput) {
95
- newActiveSessionTime = activeSessionTime + (now - (timeOfLastTextInput || 0));
96
- newTextInputCount = actionTypeCount.textInputCount;
84
+ previousTrType = pluginState.previousTrType;
85
+ if (shouldSkipTr(tr)) {
86
+ return pluginState;
87
+ }
88
+ var trType = checkTrActionType(tr);
89
+ var shouldNotIncrementActionCount = false;
90
+ var shouldSetTimeOfLastTextInput = false;
91
+ var isTextInput = false;
92
+ if (trType) {
93
+ var _trType$extraData, _previousTrType$extra;
94
+ var isNotNewStatus = trType.type === ActionType.UPDATING_STATUS && (previousTrType === null || previousTrType === void 0 ? void 0 : previousTrType.type) === ActionType.UPDATING_STATUS && (trType === null || trType === void 0 || (_trType$extraData = trType.extraData) === null || _trType$extraData === void 0 ? void 0 : _trType$extraData.statusId) === (previousTrType === null || previousTrType === void 0 || (_previousTrType$extra = previousTrType.extraData) === null || _previousTrType$extra === void 0 ? void 0 : _previousTrType$extra.statusId);
95
+ var isAddingTextToListNode = trType.type === ActionType.TEXT_INPUT && !!previousTrType && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type);
96
+ var isAddingNewListItemAfterTextInput = !!previousTrType && previousTrType.type === ActionType.TEXT_INPUT && [ActionType.UPDATING_NEW_LIST_TYPE_ITEM].includes(trType.type);
97
+
98
+ // Check if tr is textInput and only increment textInputCount if previous action was not textInput
99
+ isTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED].includes(trType.type);
100
+
101
+ // timeOfLastTextInput should be set if tr includes continuous text input on the same node
102
+ shouldSetTimeOfLastTextInput = [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE, ActionType.UPDATING_STATUS].includes(trType.type) || isNotNewStatus;
103
+
104
+ // Should not increase action count if tr is text input,
105
+ // empty line added or deleted, updating new list item or is updating same status node
106
+
107
+ shouldNotIncrementActionCount = isTextInput || isNotNewStatus || isAddingTextToListNode || isAddingNewListItemAfterTextInput;
108
+ }
109
+ var newTextInputCount = isTextInput ? actionTypeCount.textInputCount + 1 : actionTypeCount.textInputCount;
110
+ var newTotalActionCount = totalActionCount + 1;
111
+ if (timeOfLastTextInput && shouldNotIncrementActionCount) {
97
112
  newTotalActionCount = totalActionCount;
98
113
  }
114
+ if (timeOfLastTextInput && isTextInput && previousTrType && [ActionType.TEXT_INPUT, ActionType.EMPTY_LINE_ADDED_OR_DELETED, ActionType.UPDATING_NEW_LIST_TYPE_ITEM, ActionType.INSERTING_NEW_LIST_TYPE_NODE].includes(previousTrType.type)) {
115
+ newTextInputCount = actionTypeCount.textInputCount;
116
+ }
99
117
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
100
- activeSessionTime: newActiveSessionTime,
118
+ activeSessionTime: now - intentToStartEditTime,
101
119
  totalActionCount: newTotalActionCount,
102
- timeOfLastTextInput: isActionTextInput ? now : undefined,
120
+ timeOfLastTextInput: shouldSetTimeOfLastTextInput ? now : undefined,
103
121
  contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
104
122
  actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
105
123
  textInputCount: newTextInputCount
106
124
  }),
107
125
  intentToStartEditTime: intentToStartEditTime,
108
- shouldPersistActiveSession: shouldPersistActiveSession
126
+ shouldPersistActiveSession: shouldPersistActiveSession,
127
+ previousTrType: trType
109
128
  });
110
129
  return newPluginState;
111
130
  }
@@ -0,0 +1,152 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { InsertTypeAheadStep, LinkMetaStep } from '@atlaskit/adf-schema/steps';
3
+ import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
4
+ export var ActionType = /*#__PURE__*/function (ActionType) {
5
+ ActionType["TEXT_INPUT"] = "textInput";
6
+ ActionType["EMPTY_LINE_ADDED_OR_DELETED"] = "emptyLineAddedOrDeleted";
7
+ ActionType["INSERTED_FROM_TYPE_AHEAD"] = "insertedFromTypeAhead";
8
+ ActionType["INSERTING_NEW_LIST_TYPE_NODE"] = "insertingNewListTypeNode";
9
+ ActionType["UPDATING_NEW_LIST_TYPE_ITEM"] = "updatingNewListItem";
10
+ ActionType["ADDING_LINK"] = "addingLink";
11
+ ActionType["UPDATING_STATUS"] = "updatingStatus";
12
+ return ActionType;
13
+ }({});
14
+ var isTextInput = function isTextInput(step) {
15
+ var _ref = step,
16
+ content = _ref.slice.content,
17
+ from = _ref.from,
18
+ to = _ref.to;
19
+ var node = content.firstChild;
20
+ var isAddingCharacter = from === to && content.childCount === 1 && !!node && !!node.text && node.text.length === 1;
21
+ var isDeletingCharacter = to - from === 1 && content.childCount === 0;
22
+ return isAddingCharacter || isDeletingCharacter;
23
+ };
24
+ var isEmptyLineAddedOrDeleted = function isEmptyLineAddedOrDeleted(step) {
25
+ var _ref2 = step,
26
+ content = _ref2.slice.content,
27
+ from = _ref2.from,
28
+ to = _ref2.to;
29
+ var isEmptyLineDeleted = to - from === 2 && content.size === 0;
30
+ if (isEmptyLineDeleted) {
31
+ return true;
32
+ }
33
+ var isEmptyLineAdded = false;
34
+ content.forEach(function (node) {
35
+ isEmptyLineAdded = node.type.name === 'paragraph' && node.content.size === 0;
36
+ });
37
+ return isEmptyLineAdded;
38
+ };
39
+ var isUpdatingListTypeNode = function isUpdatingListTypeNode(step) {
40
+ var slice = step.slice;
41
+ var childCount = slice.content.childCount;
42
+ if (childCount < 1) {
43
+ return false;
44
+ }
45
+ var isListTypeNode = false;
46
+ slice.content.forEach(function (node) {
47
+ isListTypeNode = ['decisionList', 'decisionItem', 'bulletList', 'listItem', 'orderedList', 'taskList', 'taskItem'].includes(node.type.name);
48
+ });
49
+ if (!isListTypeNode) {
50
+ return false;
51
+ }
52
+ return childCount === 1 ? ActionType.INSERTING_NEW_LIST_TYPE_NODE : ActionType.UPDATING_NEW_LIST_TYPE_ITEM;
53
+ };
54
+ var isUpdatingStatus = function isUpdatingStatus(step) {
55
+ var slice = step.slice;
56
+ var firstChild = slice.content.firstChild;
57
+ if (!firstChild) {
58
+ return undefined;
59
+ }
60
+ return firstChild.type.name === 'status' && firstChild.attrs.localId;
61
+ };
62
+ var isAddingLink = function isAddingLink(tr) {
63
+ var hasLinkStep = tr.steps.some(function (step) {
64
+ return step instanceof LinkMetaStep;
65
+ });
66
+ var hasReplaceStep = tr.steps.some(function (step) {
67
+ return step instanceof ReplaceStep;
68
+ });
69
+ return hasLinkStep && !hasReplaceStep;
70
+ };
71
+ var isTypeAheadRelatedTr = function isTypeAheadRelatedTr(tr) {
72
+ var _tr$getMeta;
73
+ if (((_tr$getMeta = tr.getMeta('typeAheadPlugin$')) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === 'INSERT_RAW_QUERY') {
74
+ return 'INSERT_RAW_QUERY';
75
+ }
76
+ if (!tr.getMeta('appendedTransaction')) {
77
+ return false;
78
+ }
79
+ var insertTypeAheadStep = tr.steps.find(function (step) {
80
+ return step instanceof InsertTypeAheadStep;
81
+ });
82
+ var replaceStep = tr.steps.find(function (step) {
83
+ return step instanceof ReplaceStep;
84
+ });
85
+ if (!insertTypeAheadStep || !replaceStep) {
86
+ return false;
87
+ }
88
+ return insertTypeAheadStep instanceof InsertTypeAheadStep && insertTypeAheadStep.stage;
89
+ };
90
+ export var shouldSkipTr = function shouldSkipTr(tr) {
91
+ var resolvingLink = isAddingLink(tr);
92
+ if (resolvingLink) {
93
+ return true;
94
+ }
95
+ var typeAheadRelatedTr = isTypeAheadRelatedTr(tr);
96
+ if (typeAheadRelatedTr) {
97
+ return typeAheadRelatedTr !== 'INSERTING_ITEM';
98
+ } else {
99
+ return tr.getMeta('appendedTransaction');
100
+ }
101
+ };
102
+ export var checkTrActionType = function checkTrActionType(tr) {
103
+ if (tr.getMeta('input_rule_plugin_transaction')) {
104
+ return {
105
+ type: ActionType.INSERTING_NEW_LIST_TYPE_NODE
106
+ };
107
+ }
108
+ var stepsLength = tr.steps.length;
109
+ if (stepsLength <= 0) {
110
+ return undefined;
111
+ }
112
+ if (isAddingLink(tr)) {
113
+ return {
114
+ type: ActionType.ADDING_LINK
115
+ };
116
+ }
117
+ var _tr$steps = _slicedToArray(tr.steps, 1),
118
+ firstStep = _tr$steps[0];
119
+ var isReplaceStep = firstStep instanceof ReplaceStep;
120
+ var isReplaceAroundStep = firstStep instanceof ReplaceAroundStep;
121
+ if (!isReplaceStep && !isReplaceAroundStep) {
122
+ return undefined;
123
+ }
124
+ if (isReplaceStep) {
125
+ if (isTextInput(firstStep)) {
126
+ return {
127
+ type: ActionType.TEXT_INPUT
128
+ };
129
+ }
130
+ if (isEmptyLineAddedOrDeleted(firstStep)) {
131
+ return {
132
+ type: ActionType.EMPTY_LINE_ADDED_OR_DELETED
133
+ };
134
+ }
135
+ var statusId = isUpdatingStatus(firstStep);
136
+ if (statusId) {
137
+ return {
138
+ type: ActionType.UPDATING_STATUS,
139
+ extraData: {
140
+ statusId: statusId
141
+ }
142
+ };
143
+ }
144
+ }
145
+ var updatingListTypeNode = isUpdatingListTypeNode(firstStep);
146
+ if (updatingListTypeNode) {
147
+ return {
148
+ type: updatingListTypeNode
149
+ };
150
+ }
151
+ return undefined;
152
+ };
@@ -3,6 +3,7 @@ import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
4
4
  import { PluginKey, Selection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { type MetricsPlugin } from '../metricsPluginType';
6
+ import { type TrActionType } from './utils/check-tr-action-type';
6
7
  export declare const metricsKey: PluginKey<any>;
7
8
  export type MetricsState = {
8
9
  intentToStartEditTime?: number;
@@ -14,6 +15,7 @@ export type MetricsState = {
14
15
  timeOfLastTextInput?: number;
15
16
  shouldPersistActiveSession?: boolean;
16
17
  initialContent?: Fragment;
18
+ previousTrType?: TrActionType;
17
19
  };
18
20
  export type ActionByType = {
19
21
  textInputCount: number;
@@ -0,0 +1,18 @@
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare enum ActionType {
3
+ TEXT_INPUT = "textInput",
4
+ EMPTY_LINE_ADDED_OR_DELETED = "emptyLineAddedOrDeleted",
5
+ INSERTED_FROM_TYPE_AHEAD = "insertedFromTypeAhead",
6
+ INSERTING_NEW_LIST_TYPE_NODE = "insertingNewListTypeNode",
7
+ UPDATING_NEW_LIST_TYPE_ITEM = "updatingNewListItem",
8
+ ADDING_LINK = "addingLink",
9
+ UPDATING_STATUS = "updatingStatus"
10
+ }
11
+ export declare const shouldSkipTr: (tr: ReadonlyTransaction) => boolean;
12
+ export type TrActionType = {
13
+ type: ActionType;
14
+ extraData?: {
15
+ statusId?: string;
16
+ };
17
+ } | undefined;
18
+ export declare const checkTrActionType: (tr: ReadonlyTransaction) => TrActionType;
@@ -3,6 +3,7 @@ import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
4
4
  import { PluginKey, Selection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { type MetricsPlugin } from '../metricsPluginType';
6
+ import { type TrActionType } from './utils/check-tr-action-type';
6
7
  export declare const metricsKey: PluginKey<any>;
7
8
  export type MetricsState = {
8
9
  intentToStartEditTime?: number;
@@ -14,6 +15,7 @@ export type MetricsState = {
14
15
  timeOfLastTextInput?: number;
15
16
  shouldPersistActiveSession?: boolean;
16
17
  initialContent?: Fragment;
18
+ previousTrType?: TrActionType;
17
19
  };
18
20
  export type ActionByType = {
19
21
  textInputCount: number;
@@ -0,0 +1,18 @@
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare enum ActionType {
3
+ TEXT_INPUT = "textInput",
4
+ EMPTY_LINE_ADDED_OR_DELETED = "emptyLineAddedOrDeleted",
5
+ INSERTED_FROM_TYPE_AHEAD = "insertedFromTypeAhead",
6
+ INSERTING_NEW_LIST_TYPE_NODE = "insertingNewListTypeNode",
7
+ UPDATING_NEW_LIST_TYPE_ITEM = "updatingNewListItem",
8
+ ADDING_LINK = "addingLink",
9
+ UPDATING_STATUS = "updatingStatus"
10
+ }
11
+ export declare const shouldSkipTr: (tr: ReadonlyTransaction) => boolean;
12
+ export type TrActionType = {
13
+ type: ActionType;
14
+ extraData?: {
15
+ statusId?: string;
16
+ };
17
+ } | undefined;
18
+ export declare const checkTrActionType: (tr: ReadonlyTransaction) => TrActionType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-metrics",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "Metrics plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@atlaskit/adf-schema": "^47.2.1",
28
- "@atlaskit/editor-common": "^99.17.0",
28
+ "@atlaskit/editor-common": "^99.19.0",
29
29
  "@atlaskit/editor-plugin-analytics": "^1.12.0",
30
30
  "@atlaskit/editor-plugin-block-controls": "^2.27.0",
31
31
  "@atlaskit/editor-prosemirror": "7.0.0",