@atlaskit/editor-plugin-metrics 3.1.0 → 3.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/editor-plugin-metrics
2
2
 
3
+ ## 3.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#108974](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/108974)
8
+ [`2ed04755a098e`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/2ed04755a098e) -
9
+ ED-26233 Start activity session in metrics plugin when user starts dragging nodes and opens
10
+ element browser
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 3.1.1
17
+
18
+ ### Patch Changes
19
+
20
+ - [#112186](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/112186)
21
+ [`9462d8ca2405a`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/9462d8ca2405a) -
22
+ Bump adf-schema to 47.2.1
23
+
3
24
  ## 3.1.0
4
25
 
5
26
  ### Minor Changes
@@ -10,6 +10,7 @@ var _analytics = require("./pm-plugins/utils/analytics");
10
10
  * Metrics plugin to be added to an `EditorPresetBuilder` and used with `ComposableEditor`
11
11
  * from `@atlaskit/editor-core`.
12
12
  */
13
+
13
14
  var metricsPlugin = exports.metricsPlugin = function metricsPlugin(_ref) {
14
15
  var api = _ref.api;
15
16
  return {
@@ -23,24 +24,67 @@ var metricsPlugin = exports.metricsPlugin = function metricsPlugin(_ref) {
23
24
  }];
24
25
  },
25
26
  commands: {
26
- stopActiveSession: function stopActiveSession() {
27
+ startActiveSessionTimer: function startActiveSessionTimer() {
27
28
  return function (_ref2) {
28
29
  var tr = _ref2.tr;
30
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
31
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.intentToStartEditTime)) {
32
+ return tr;
33
+ }
34
+ return tr.setMeta(_main.metricsKey, {
35
+ shouldStartTimer: true,
36
+ shouldPersistActiveSession: false
37
+ });
38
+ };
39
+ },
40
+ stopActiveSession: function stopActiveSession() {
41
+ return function (_ref3) {
42
+ var tr = _ref3.tr;
29
43
  if (!api) {
30
44
  return tr;
31
45
  }
32
- var newTr = tr;
33
46
  var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
47
+ if (pluginState !== null && pluginState !== void 0 && pluginState.shouldPersistActiveSession) {
48
+ return tr;
49
+ }
34
50
  if (pluginState && pluginState.totalActionCount > 0 && pluginState.activeSessionTime > 0) {
35
51
  var payloadToSend = (0, _analytics.getAnalyticsPayload)({
36
52
  currentContent: tr.doc.content,
37
53
  pluginState: pluginState
38
54
  });
39
- api === null || api === void 0 || api.analytics.actions.attachAnalyticsEvent(payloadToSend)(newTr);
55
+ api === null || api === void 0 || api.analytics.actions.attachAnalyticsEvent(payloadToSend)(tr);
40
56
  }
41
- newTr.setMeta(_main.metricsKey, {
57
+ tr.setMeta(_main.metricsKey, {
42
58
  stopActiveSession: true
43
59
  });
60
+ return tr;
61
+ };
62
+ },
63
+ handleIntentToStartEdit: function handleIntentToStartEdit(_ref4) {
64
+ var newSelection = _ref4.newSelection,
65
+ _ref4$shouldStartTime = _ref4.shouldStartTimer,
66
+ shouldStartTimer = _ref4$shouldStartTime === void 0 ? true : _ref4$shouldStartTime,
67
+ shouldPersistActiveSession = _ref4.shouldPersistActiveSession;
68
+ return function (_ref5) {
69
+ var tr = _ref5.tr;
70
+ if (!api) {
71
+ return tr;
72
+ }
73
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
74
+ if (!pluginState || pluginState.intentToStartEditTime) {
75
+ if (shouldPersistActiveSession !== (pluginState === null || pluginState === void 0 ? void 0 : pluginState.shouldPersistActiveSession)) {
76
+ return tr.setMeta(_main.metricsKey, {
77
+ shouldPersistActiveSession: shouldPersistActiveSession
78
+ });
79
+ }
80
+ }
81
+ var newTr = tr;
82
+ newTr.setMeta(_main.metricsKey, {
83
+ intentToStartEditTime: performance.now(),
84
+ shouldStartTimer: shouldStartTimer,
85
+ newSelection: newSelection,
86
+ shouldPersistActiveSession: shouldPersistActiveSession
87
+ });
44
88
  return newTr;
45
89
  };
46
90
  }
@@ -46,33 +46,48 @@ 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;
50
+ if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
51
+ return pluginState;
52
+ }
49
53
  var meta = tr.getMeta(metricsKey);
50
- var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
54
+
55
+ // If the active session is stopped, reset the plugin state, and set initialContent to new doc content
51
56
  if (meta && meta.stopActiveSession) {
52
57
  return _objectSpread(_objectSpread({}, initialPluginState), {}, {
53
58
  initialContent: newState.doc.content
54
59
  });
55
60
  }
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();
68
+ var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
69
+ var now = performance.now();
56
70
  if (!intentToStartEditTime) {
57
- if (tr.docChanged && !tr.getMeta('replaceDocument')) {
58
- intentToStartEditTime = performance.now();
71
+ if (docChangedWithoutAnalytics || tr.storedMarksSet) {
72
+ intentToStartEditTime = now;
59
73
  } else {
60
- return pluginState;
74
+ return _objectSpread({}, pluginState);
61
75
  }
62
76
  }
77
+
78
+ // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
79
+ // shouldPersistActiveSession is set to true when dragging block controls and when insert menu is open
80
+ // Timer should start when menu closes or dragging stops
81
+ if (intentToStartEditTime && meta !== null && meta !== void 0 && meta.shouldStartTimer && !pluginState.shouldPersistActiveSession) {
82
+ timer.startTimer();
83
+ }
63
84
  var undoCount = (0, _isNonTextUndo.isNonTextUndo)(tr) ? 1 : 0;
64
85
  var newActionTypeCount = pluginState.actionTypeCount ? _objectSpread(_objectSpread({}, pluginState.actionTypeCount), {}, {
65
86
  undoCount: pluginState.actionTypeCount.undoCount + undoCount
66
87
  }) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
67
88
  undoCount: undoCount
68
89
  });
69
- var canIgnoreTr = function canIgnoreTr() {
70
- return !tr.steps.every(function (e) {
71
- return e instanceof _steps.AnalyticsStep;
72
- });
73
- };
74
- if (tr.docChanged && canIgnoreTr()) {
75
- var now = performance.now();
90
+ if (docChangedWithoutAnalytics) {
76
91
  timer.startTimer();
77
92
  var actionTypeCount = pluginState.actionTypeCount,
78
93
  timeOfLastTextInput = pluginState.timeOfLastTextInput,
@@ -95,18 +110,44 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
95
110
  contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
96
111
  actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
97
112
  textInputCount: newTextInputCount
98
- })
113
+ }),
114
+ intentToStartEditTime: intentToStartEditTime,
115
+ shouldPersistActiveSession: shouldPersistActiveSession
99
116
  });
100
117
  return newPluginState;
101
118
  }
102
119
  return _objectSpread(_objectSpread({}, pluginState), {}, {
103
120
  lastSelection: (meta === null || meta === void 0 ? void 0 : meta.newSelection) || pluginState.lastSelection,
104
121
  intentToStartEditTime: intentToStartEditTime,
105
- actionTypeCount: newActionTypeCount
122
+ actionTypeCount: newActionTypeCount,
123
+ shouldPersistActiveSession: shouldPersistActiveSession
106
124
  });
107
125
  }
108
126
  },
109
127
  view: function view(_view) {
128
+ var _api$blockControls;
129
+ var handleIsDraggingChanged = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(function (_ref) {
130
+ var nextSharedState = _ref.nextSharedState,
131
+ prevSharedState = _ref.prevSharedState;
132
+ if (nextSharedState) {
133
+ api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
134
+ var tr = _ref2.tr;
135
+ if (!(prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging) && nextSharedState.isDragging) {
136
+ api === null || api === void 0 || api.metrics.commands.handleIntentToStartEdit({
137
+ shouldStartTimer: false,
138
+ shouldPersistActiveSession: true
139
+ })({
140
+ tr: tr
141
+ });
142
+ } else if (prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging && !nextSharedState.isDragging) {
143
+ api === null || api === void 0 || api.metrics.commands.startActiveSessionTimer()({
144
+ tr: tr
145
+ });
146
+ }
147
+ return tr;
148
+ });
149
+ }
150
+ });
110
151
  var fireAnalyticsEvent = function fireAnalyticsEvent() {
111
152
  var pluginState = metricsKey.getState(_view.state);
112
153
  if (!pluginState) {
@@ -133,6 +174,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
133
174
  fireAnalyticsEvent();
134
175
  timer.cleanupTimer();
135
176
  unbindBeforeUnload();
177
+ handleIsDraggingChanged === null || handleIsDraggingChanged === void 0 || handleIsDraggingChanged();
136
178
  }
137
179
  };
138
180
  },
@@ -140,19 +182,12 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
140
182
  handleDOMEvents: {
141
183
  click: function click(view) {
142
184
  var _pluginState$lastSele, _pluginState$lastSele2;
143
- var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
144
- if (!pluginState || pluginState.intentToStartEditTime) {
145
- return false;
146
- }
147
185
  var newSelection = view.state.tr.selection;
148
- var newTr = view.state.tr;
186
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
149
187
  if ((pluginState === null || pluginState === void 0 || (_pluginState$lastSele = pluginState.lastSelection) === null || _pluginState$lastSele === void 0 ? void 0 : _pluginState$lastSele.from) !== newSelection.from && (pluginState === null || pluginState === void 0 || (_pluginState$lastSele2 = pluginState.lastSelection) === null || _pluginState$lastSele2 === void 0 ? void 0 : _pluginState$lastSele2.to) !== newSelection.to) {
150
- newTr.setMeta(metricsKey, {
151
- intentToStartEditTime: performance.now(),
188
+ api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.metrics.commands.handleIntentToStartEdit({
152
189
  newSelection: newSelection
153
- });
154
- view.dispatch(newTr);
155
- timer.startTimer();
190
+ }));
156
191
  }
157
192
  return false;
158
193
  }
@@ -4,6 +4,7 @@ import { getAnalyticsPayload } from './pm-plugins/utils/analytics';
4
4
  * Metrics plugin to be added to an `EditorPresetBuilder` and used with `ComposableEditor`
5
5
  * from `@atlaskit/editor-core`.
6
6
  */
7
+
7
8
  export const metricsPlugin = ({
8
9
  api
9
10
  }) => ({
@@ -15,24 +16,65 @@ export const metricsPlugin = ({
15
16
  }];
16
17
  },
17
18
  commands: {
19
+ startActiveSessionTimer: () => ({
20
+ tr
21
+ }) => {
22
+ const pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
23
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.intentToStartEditTime)) {
24
+ return tr;
25
+ }
26
+ return tr.setMeta(metricsKey, {
27
+ shouldStartTimer: true,
28
+ shouldPersistActiveSession: false
29
+ });
30
+ },
18
31
  stopActiveSession: () => ({
19
32
  tr
20
33
  }) => {
21
34
  if (!api) {
22
35
  return tr;
23
36
  }
24
- const newTr = tr;
25
37
  const pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
38
+ if (pluginState !== null && pluginState !== void 0 && pluginState.shouldPersistActiveSession) {
39
+ return tr;
40
+ }
26
41
  if (pluginState && pluginState.totalActionCount > 0 && pluginState.activeSessionTime > 0) {
27
42
  const payloadToSend = getAnalyticsPayload({
28
43
  currentContent: tr.doc.content,
29
44
  pluginState
30
45
  });
31
- api === null || api === void 0 ? void 0 : api.analytics.actions.attachAnalyticsEvent(payloadToSend)(newTr);
46
+ api === null || api === void 0 ? void 0 : api.analytics.actions.attachAnalyticsEvent(payloadToSend)(tr);
32
47
  }
33
- newTr.setMeta(metricsKey, {
48
+ tr.setMeta(metricsKey, {
34
49
  stopActiveSession: true
35
50
  });
51
+ return tr;
52
+ },
53
+ handleIntentToStartEdit: ({
54
+ newSelection,
55
+ shouldStartTimer = true,
56
+ shouldPersistActiveSession
57
+ }) => ({
58
+ tr
59
+ }) => {
60
+ if (!api) {
61
+ return tr;
62
+ }
63
+ const pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
64
+ if (!pluginState || pluginState.intentToStartEditTime) {
65
+ if (shouldPersistActiveSession !== (pluginState === null || pluginState === void 0 ? void 0 : pluginState.shouldPersistActiveSession)) {
66
+ return tr.setMeta(metricsKey, {
67
+ shouldPersistActiveSession: shouldPersistActiveSession
68
+ });
69
+ }
70
+ }
71
+ const newTr = tr;
72
+ newTr.setMeta(metricsKey, {
73
+ intentToStartEditTime: performance.now(),
74
+ shouldStartTimer,
75
+ newSelection,
76
+ shouldPersistActiveSession
77
+ });
36
78
  return newTr;
37
79
  }
38
80
  },
@@ -37,21 +37,40 @@ 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;
41
+ if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
42
+ return pluginState;
43
+ }
40
44
  const meta = tr.getMeta(metricsKey);
41
- let intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
45
+
46
+ // If the active session is stopped, reset the plugin state, and set initialContent to new doc content
42
47
  if (meta && meta.stopActiveSession) {
43
48
  return {
44
49
  ...initialPluginState,
45
50
  initialContent: newState.doc.content
46
51
  };
47
52
  }
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();
56
+ let intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
57
+ const now = performance.now();
48
58
  if (!intentToStartEditTime) {
49
- if (tr.docChanged && !tr.getMeta('replaceDocument')) {
50
- intentToStartEditTime = performance.now();
59
+ if (docChangedWithoutAnalytics || tr.storedMarksSet) {
60
+ intentToStartEditTime = now;
51
61
  } else {
52
- return pluginState;
62
+ return {
63
+ ...pluginState
64
+ };
53
65
  }
54
66
  }
67
+
68
+ // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
69
+ // shouldPersistActiveSession is set to true when dragging block controls and when insert menu is open
70
+ // Timer should start when menu closes or dragging stops
71
+ if (intentToStartEditTime && meta !== null && meta !== void 0 && meta.shouldStartTimer && !pluginState.shouldPersistActiveSession) {
72
+ timer.startTimer();
73
+ }
55
74
  const undoCount = isNonTextUndo(tr) ? 1 : 0;
56
75
  const newActionTypeCount = pluginState.actionTypeCount ? {
57
76
  ...pluginState.actionTypeCount,
@@ -60,9 +79,7 @@ export const createPlugin = api => {
60
79
  ...initialPluginState.actionTypeCount,
61
80
  undoCount
62
81
  };
63
- const canIgnoreTr = () => !tr.steps.every(e => e instanceof AnalyticsStep);
64
- if (tr.docChanged && canIgnoreTr()) {
65
- const now = performance.now();
82
+ if (docChangedWithoutAnalytics) {
66
83
  timer.startTimer();
67
84
  const {
68
85
  actionTypeCount,
@@ -89,7 +106,9 @@ export const createPlugin = api => {
89
106
  actionTypeCount: {
90
107
  ...newActionTypeCount,
91
108
  textInputCount: newTextInputCount
92
- }
109
+ },
110
+ intentToStartEditTime,
111
+ shouldPersistActiveSession
93
112
  };
94
113
  return newPluginState;
95
114
  }
@@ -97,11 +116,37 @@ export const createPlugin = api => {
97
116
  ...pluginState,
98
117
  lastSelection: (meta === null || meta === void 0 ? void 0 : meta.newSelection) || pluginState.lastSelection,
99
118
  intentToStartEditTime,
100
- actionTypeCount: newActionTypeCount
119
+ actionTypeCount: newActionTypeCount,
120
+ shouldPersistActiveSession
101
121
  };
102
122
  }
103
123
  },
104
124
  view(view) {
125
+ var _api$blockControls;
126
+ const handleIsDraggingChanged = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(({
127
+ nextSharedState,
128
+ prevSharedState
129
+ }) => {
130
+ if (nextSharedState) {
131
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(({
132
+ tr
133
+ }) => {
134
+ if (!(prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging) && nextSharedState.isDragging) {
135
+ api === null || api === void 0 ? void 0 : api.metrics.commands.handleIntentToStartEdit({
136
+ shouldStartTimer: false,
137
+ shouldPersistActiveSession: true
138
+ })({
139
+ tr
140
+ });
141
+ } else if (prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging && !nextSharedState.isDragging) {
142
+ api === null || api === void 0 ? void 0 : api.metrics.commands.startActiveSessionTimer()({
143
+ tr
144
+ });
145
+ }
146
+ return tr;
147
+ });
148
+ }
149
+ });
105
150
  const fireAnalyticsEvent = () => {
106
151
  const pluginState = metricsKey.getState(view.state);
107
152
  if (!pluginState) {
@@ -128,6 +173,7 @@ export const createPlugin = api => {
128
173
  fireAnalyticsEvent();
129
174
  timer.cleanupTimer();
130
175
  unbindBeforeUnload();
176
+ handleIsDraggingChanged === null || handleIsDraggingChanged === void 0 ? void 0 : handleIsDraggingChanged();
131
177
  }
132
178
  };
133
179
  },
@@ -135,19 +181,12 @@ export const createPlugin = api => {
135
181
  handleDOMEvents: {
136
182
  click: view => {
137
183
  var _pluginState$lastSele, _pluginState$lastSele2;
138
- const pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
139
- if (!pluginState || pluginState.intentToStartEditTime) {
140
- return false;
141
- }
142
184
  const newSelection = view.state.tr.selection;
143
- const newTr = view.state.tr;
185
+ const pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
144
186
  if ((pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$lastSele = pluginState.lastSelection) === null || _pluginState$lastSele === void 0 ? void 0 : _pluginState$lastSele.from) !== newSelection.from && (pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$lastSele2 = pluginState.lastSelection) === null || _pluginState$lastSele2 === void 0 ? void 0 : _pluginState$lastSele2.to) !== newSelection.to) {
145
- newTr.setMeta(metricsKey, {
146
- intentToStartEditTime: performance.now(),
147
- newSelection: newSelection
148
- });
149
- view.dispatch(newTr);
150
- timer.startTimer();
187
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.metrics.commands.handleIntentToStartEdit({
188
+ newSelection
189
+ }));
151
190
  }
152
191
  return false;
153
192
  }
@@ -4,6 +4,7 @@ import { getAnalyticsPayload } from './pm-plugins/utils/analytics';
4
4
  * Metrics plugin to be added to an `EditorPresetBuilder` and used with `ComposableEditor`
5
5
  * from `@atlaskit/editor-core`.
6
6
  */
7
+
7
8
  export var metricsPlugin = function metricsPlugin(_ref) {
8
9
  var api = _ref.api;
9
10
  return {
@@ -17,24 +18,67 @@ export var metricsPlugin = function metricsPlugin(_ref) {
17
18
  }];
18
19
  },
19
20
  commands: {
20
- stopActiveSession: function stopActiveSession() {
21
+ startActiveSessionTimer: function startActiveSessionTimer() {
21
22
  return function (_ref2) {
22
23
  var tr = _ref2.tr;
24
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
25
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.intentToStartEditTime)) {
26
+ return tr;
27
+ }
28
+ return tr.setMeta(metricsKey, {
29
+ shouldStartTimer: true,
30
+ shouldPersistActiveSession: false
31
+ });
32
+ };
33
+ },
34
+ stopActiveSession: function stopActiveSession() {
35
+ return function (_ref3) {
36
+ var tr = _ref3.tr;
23
37
  if (!api) {
24
38
  return tr;
25
39
  }
26
- var newTr = tr;
27
40
  var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
41
+ if (pluginState !== null && pluginState !== void 0 && pluginState.shouldPersistActiveSession) {
42
+ return tr;
43
+ }
28
44
  if (pluginState && pluginState.totalActionCount > 0 && pluginState.activeSessionTime > 0) {
29
45
  var payloadToSend = getAnalyticsPayload({
30
46
  currentContent: tr.doc.content,
31
47
  pluginState: pluginState
32
48
  });
33
- api === null || api === void 0 || api.analytics.actions.attachAnalyticsEvent(payloadToSend)(newTr);
49
+ api === null || api === void 0 || api.analytics.actions.attachAnalyticsEvent(payloadToSend)(tr);
34
50
  }
35
- newTr.setMeta(metricsKey, {
51
+ tr.setMeta(metricsKey, {
36
52
  stopActiveSession: true
37
53
  });
54
+ return tr;
55
+ };
56
+ },
57
+ handleIntentToStartEdit: function handleIntentToStartEdit(_ref4) {
58
+ var newSelection = _ref4.newSelection,
59
+ _ref4$shouldStartTime = _ref4.shouldStartTimer,
60
+ shouldStartTimer = _ref4$shouldStartTime === void 0 ? true : _ref4$shouldStartTime,
61
+ shouldPersistActiveSession = _ref4.shouldPersistActiveSession;
62
+ return function (_ref5) {
63
+ var tr = _ref5.tr;
64
+ if (!api) {
65
+ return tr;
66
+ }
67
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
68
+ if (!pluginState || pluginState.intentToStartEditTime) {
69
+ if (shouldPersistActiveSession !== (pluginState === null || pluginState === void 0 ? void 0 : pluginState.shouldPersistActiveSession)) {
70
+ return tr.setMeta(metricsKey, {
71
+ shouldPersistActiveSession: shouldPersistActiveSession
72
+ });
73
+ }
74
+ }
75
+ var newTr = tr;
76
+ newTr.setMeta(metricsKey, {
77
+ intentToStartEditTime: performance.now(),
78
+ shouldStartTimer: shouldStartTimer,
79
+ newSelection: newSelection,
80
+ shouldPersistActiveSession: shouldPersistActiveSession
81
+ });
38
82
  return newTr;
39
83
  };
40
84
  }
@@ -39,33 +39,48 @@ 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;
43
+ if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
44
+ return pluginState;
45
+ }
42
46
  var meta = tr.getMeta(metricsKey);
43
- var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
47
+
48
+ // If the active session is stopped, reset the plugin state, and set initialContent to new doc content
44
49
  if (meta && meta.stopActiveSession) {
45
50
  return _objectSpread(_objectSpread({}, initialPluginState), {}, {
46
51
  initialContent: newState.doc.content
47
52
  });
48
53
  }
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();
61
+ var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
62
+ var now = performance.now();
49
63
  if (!intentToStartEditTime) {
50
- if (tr.docChanged && !tr.getMeta('replaceDocument')) {
51
- intentToStartEditTime = performance.now();
64
+ if (docChangedWithoutAnalytics || tr.storedMarksSet) {
65
+ intentToStartEditTime = now;
52
66
  } else {
53
- return pluginState;
67
+ return _objectSpread({}, pluginState);
54
68
  }
55
69
  }
70
+
71
+ // Start active session timer if intentToStartEditTime is set and shouldStartTimer is true
72
+ // shouldPersistActiveSession is set to true when dragging block controls and when insert menu is open
73
+ // Timer should start when menu closes or dragging stops
74
+ if (intentToStartEditTime && meta !== null && meta !== void 0 && meta.shouldStartTimer && !pluginState.shouldPersistActiveSession) {
75
+ timer.startTimer();
76
+ }
56
77
  var undoCount = isNonTextUndo(tr) ? 1 : 0;
57
78
  var newActionTypeCount = pluginState.actionTypeCount ? _objectSpread(_objectSpread({}, pluginState.actionTypeCount), {}, {
58
79
  undoCount: pluginState.actionTypeCount.undoCount + undoCount
59
80
  }) : _objectSpread(_objectSpread({}, initialPluginState.actionTypeCount), {}, {
60
81
  undoCount: undoCount
61
82
  });
62
- var canIgnoreTr = function canIgnoreTr() {
63
- return !tr.steps.every(function (e) {
64
- return e instanceof AnalyticsStep;
65
- });
66
- };
67
- if (tr.docChanged && canIgnoreTr()) {
68
- var now = performance.now();
83
+ if (docChangedWithoutAnalytics) {
69
84
  timer.startTimer();
70
85
  var actionTypeCount = pluginState.actionTypeCount,
71
86
  timeOfLastTextInput = pluginState.timeOfLastTextInput,
@@ -88,18 +103,44 @@ export var createPlugin = function createPlugin(api) {
88
103
  contentSizeChanged: pluginState.contentSizeChanged + (newState.doc.content.size - oldState.doc.content.size),
89
104
  actionTypeCount: _objectSpread(_objectSpread({}, newActionTypeCount), {}, {
90
105
  textInputCount: newTextInputCount
91
- })
106
+ }),
107
+ intentToStartEditTime: intentToStartEditTime,
108
+ shouldPersistActiveSession: shouldPersistActiveSession
92
109
  });
93
110
  return newPluginState;
94
111
  }
95
112
  return _objectSpread(_objectSpread({}, pluginState), {}, {
96
113
  lastSelection: (meta === null || meta === void 0 ? void 0 : meta.newSelection) || pluginState.lastSelection,
97
114
  intentToStartEditTime: intentToStartEditTime,
98
- actionTypeCount: newActionTypeCount
115
+ actionTypeCount: newActionTypeCount,
116
+ shouldPersistActiveSession: shouldPersistActiveSession
99
117
  });
100
118
  }
101
119
  },
102
120
  view: function view(_view) {
121
+ var _api$blockControls;
122
+ var handleIsDraggingChanged = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(function (_ref) {
123
+ var nextSharedState = _ref.nextSharedState,
124
+ prevSharedState = _ref.prevSharedState;
125
+ if (nextSharedState) {
126
+ api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
127
+ var tr = _ref2.tr;
128
+ if (!(prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging) && nextSharedState.isDragging) {
129
+ api === null || api === void 0 || api.metrics.commands.handleIntentToStartEdit({
130
+ shouldStartTimer: false,
131
+ shouldPersistActiveSession: true
132
+ })({
133
+ tr: tr
134
+ });
135
+ } else if (prevSharedState !== null && prevSharedState !== void 0 && prevSharedState.isDragging && !nextSharedState.isDragging) {
136
+ api === null || api === void 0 || api.metrics.commands.startActiveSessionTimer()({
137
+ tr: tr
138
+ });
139
+ }
140
+ return tr;
141
+ });
142
+ }
143
+ });
103
144
  var fireAnalyticsEvent = function fireAnalyticsEvent() {
104
145
  var pluginState = metricsKey.getState(_view.state);
105
146
  if (!pluginState) {
@@ -126,6 +167,7 @@ export var createPlugin = function createPlugin(api) {
126
167
  fireAnalyticsEvent();
127
168
  timer.cleanupTimer();
128
169
  unbindBeforeUnload();
170
+ handleIsDraggingChanged === null || handleIsDraggingChanged === void 0 || handleIsDraggingChanged();
129
171
  }
130
172
  };
131
173
  },
@@ -133,19 +175,12 @@ export var createPlugin = function createPlugin(api) {
133
175
  handleDOMEvents: {
134
176
  click: function click(view) {
135
177
  var _pluginState$lastSele, _pluginState$lastSele2;
136
- var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
137
- if (!pluginState || pluginState.intentToStartEditTime) {
138
- return false;
139
- }
140
178
  var newSelection = view.state.tr.selection;
141
- var newTr = view.state.tr;
179
+ var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
142
180
  if ((pluginState === null || pluginState === void 0 || (_pluginState$lastSele = pluginState.lastSelection) === null || _pluginState$lastSele === void 0 ? void 0 : _pluginState$lastSele.from) !== newSelection.from && (pluginState === null || pluginState === void 0 || (_pluginState$lastSele2 = pluginState.lastSelection) === null || _pluginState$lastSele2 === void 0 ? void 0 : _pluginState$lastSele2.to) !== newSelection.to) {
143
- newTr.setMeta(metricsKey, {
144
- intentToStartEditTime: performance.now(),
181
+ api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.metrics.commands.handleIntentToStartEdit({
145
182
  newSelection: newSelection
146
- });
147
- view.dispatch(newTr);
148
- timer.startTimer();
183
+ }));
149
184
  }
150
185
  return false;
151
186
  }
@@ -1,10 +1,20 @@
1
- import type { EditorCommand, NextEditorPlugin } from '@atlaskit/editor-common/types';
1
+ import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
2
  import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
3
+ import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls';
4
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
3
5
  import type { MetricsState } from './pm-plugins/main';
6
+ type handleIntentToStartEditProps = {
7
+ newSelection?: Selection;
8
+ shouldStartTimer?: boolean;
9
+ shouldPersistActiveSession?: boolean;
10
+ };
4
11
  export type MetricsPlugin = NextEditorPlugin<'metrics', {
5
- dependencies: [AnalyticsPlugin];
12
+ dependencies: [AnalyticsPlugin, OptionalPlugin<BlockControlsPlugin>];
6
13
  sharedState: MetricsState;
7
14
  commands: {
15
+ startActiveSessionTimer: () => EditorCommand;
8
16
  stopActiveSession: () => EditorCommand;
17
+ handleIntentToStartEdit: ({ newSelection, shouldStartTimer, shouldPersistActiveSession, }: handleIntentToStartEditProps) => EditorCommand;
9
18
  };
10
19
  }>;
20
+ export {};
@@ -12,6 +12,7 @@ export type MetricsState = {
12
12
  lastSelection?: Selection;
13
13
  actionTypeCount: ActionByType;
14
14
  timeOfLastTextInput?: number;
15
+ shouldPersistActiveSession?: boolean;
15
16
  initialContent?: Fragment;
16
17
  };
17
18
  export type ActionByType = {
@@ -1,5 +1,5 @@
1
1
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
- import { MetricsState } from '../main';
2
+ import type { MetricsState } from '../main';
3
3
  export declare const getNodeChanges: ({ currentContent, pluginState, }: {
4
4
  currentContent: Fragment;
5
5
  pluginState?: MetricsState | undefined;
@@ -1,2 +1,2 @@
1
- import { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
2
  export declare const isNonTextUndo: (tr: ReadonlyTransaction) => boolean;
@@ -1,12 +1,23 @@
1
- import type { EditorCommand, NextEditorPlugin } from '@atlaskit/editor-common/types';
1
+ import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
2
  import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
3
+ import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls';
4
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
3
5
  import type { MetricsState } from './pm-plugins/main';
6
+ type handleIntentToStartEditProps = {
7
+ newSelection?: Selection;
8
+ shouldStartTimer?: boolean;
9
+ shouldPersistActiveSession?: boolean;
10
+ };
4
11
  export type MetricsPlugin = NextEditorPlugin<'metrics', {
5
12
  dependencies: [
6
- AnalyticsPlugin
13
+ AnalyticsPlugin,
14
+ OptionalPlugin<BlockControlsPlugin>
7
15
  ];
8
16
  sharedState: MetricsState;
9
17
  commands: {
18
+ startActiveSessionTimer: () => EditorCommand;
10
19
  stopActiveSession: () => EditorCommand;
20
+ handleIntentToStartEdit: ({ newSelection, shouldStartTimer, shouldPersistActiveSession, }: handleIntentToStartEditProps) => EditorCommand;
11
21
  };
12
22
  }>;
23
+ export {};
@@ -12,6 +12,7 @@ export type MetricsState = {
12
12
  lastSelection?: Selection;
13
13
  actionTypeCount: ActionByType;
14
14
  timeOfLastTextInput?: number;
15
+ shouldPersistActiveSession?: boolean;
15
16
  initialContent?: Fragment;
16
17
  };
17
18
  export type ActionByType = {
@@ -1,5 +1,5 @@
1
1
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
- import { MetricsState } from '../main';
2
+ import type { MetricsState } from '../main';
3
3
  export declare const getNodeChanges: ({ currentContent, pluginState, }: {
4
4
  currentContent: Fragment;
5
5
  pluginState?: MetricsState | undefined;
@@ -1,2 +1,2 @@
1
- import { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
2
  export declare const isNonTextUndo: (tr: ReadonlyTransaction) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-metrics",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "Metrics plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -24,11 +24,12 @@
24
24
  ".": "./src/index.ts"
25
25
  },
26
26
  "dependencies": {
27
- "@atlaskit/adf-schema": "^46.1.0",
28
- "@atlaskit/editor-common": "^99.10.0",
27
+ "@atlaskit/adf-schema": "^47.2.1",
28
+ "@atlaskit/editor-common": "^99.17.0",
29
29
  "@atlaskit/editor-plugin-analytics": "^1.12.0",
30
+ "@atlaskit/editor-plugin-block-controls": "^2.27.0",
30
31
  "@atlaskit/editor-prosemirror": "7.0.0",
31
- "@atlaskit/platform-feature-flags": "^1.0.0",
32
+ "@atlaskit/platform-feature-flags": "^1.1.0",
32
33
  "@babel/runtime": "^7.0.0",
33
34
  "bind-event-listener": "^3.0.0"
34
35
  },