@atlaskit/editor-plugin-metrics
Version:
Metrics plugin for @atlaskit/editor-core
167 lines (163 loc) • 8.65 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.metricsKey = exports.initialPluginState = exports.createPlugin = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _bindEventListener = require("bind-event-listener");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _state = require("@atlaskit/editor-prosemirror/state");
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
var _activeSessionTimer = require("./utils/active-session-timer");
var _analytics = require("./utils/analytics");
var _getNewPluginState = require("./utils/get-new-plugin-state");
var _isTrWithDocChanges = require("./utils/is-tr-with-doc-changes");
var _shouldSkipTr = require("./utils/should-skip-tr");
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; }
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; }
var metricsKey = exports.metricsKey = new _state.PluginKey('metricsPlugin');
var initialPluginState = exports.initialPluginState = {
intentToStartEditTime: undefined,
lastSelection: undefined,
activeSessionTime: 0,
totalActionCount: 0,
contentSizeChanged: 0,
shouldPersistActiveSession: undefined,
timeOfLastTextInput: undefined,
initialContent: undefined,
actionTypeCount: {
textInputCount: 0,
nodeInsertionCount: 0,
nodeAttributeChangeCount: 0,
contentMovedCount: 0,
nodeDeletionCount: 0,
undoCount: 0,
markChangeCount: 0,
contentDeletedCount: 0
},
repeatedActionCount: 0,
safeInsertCount: 0
};
var createPlugin = exports.createPlugin = function createPlugin(api, userPreferencesProvider) {
var timer = new _activeSessionTimer.ActiveSessionTimer(api);
return new _safePlugin.SafePlugin({
key: metricsKey,
state: {
init: function init(_, state) {
return _objectSpread(_objectSpread({}, initialPluginState), {}, {
initialContent: state.doc.content
});
},
// eslint-disable-next-line @typescript-eslint/max-params
apply: function apply(tr, pluginState, oldState, newState) {
var _meta$shouldPersistAc;
// Return if transaction is remote or replaceDocument is set
if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument')) {
return pluginState;
}
var meta = tr.getMeta(metricsKey);
// If the active session is stopped, reset the plugin state, and set initialContent to new doc content
if (meta && meta.stopActiveSession) {
return _objectSpread(_objectSpread({}, initialPluginState), {}, {
initialContent: newState.doc.content
});
}
var shouldPersistActiveSession = (_meta$shouldPersistAc = meta === null || meta === void 0 ? void 0 : meta.shouldPersistActiveSession) !== null && _meta$shouldPersistAc !== void 0 ? _meta$shouldPersistAc : pluginState.shouldPersistActiveSession;
var hasDocChanges = (0, _isTrWithDocChanges.isTrWithDocChanges)(tr);
var intentToStartEditTime = (meta === null || meta === void 0 ? void 0 : meta.intentToStartEditTime) || pluginState.intentToStartEditTime;
var now = performance.now();
// If there is no intentToStartEditTime and there are no doc changes, return the plugin state
if (!intentToStartEditTime && !hasDocChanges && !tr.storedMarksSet) {
return _objectSpread(_objectSpread({}, pluginState), {}, {
shouldPersistActiveSession: shouldPersistActiveSession
});
}
// Set intentToStartEditTime if it is not set and there are doc changes or marks are set
if (!intentToStartEditTime && (hasDocChanges || tr.storedMarksSet)) {
intentToStartEditTime = now;
}
// Start active session timer if intentToStartEditTime is defined, shouldStartTimer is true and shouldPersistActiveSession is false
// shouldPersistActiveSession is true when dragging block controls and when insert menu is open as user is interacting with the editor without making doc changes
// Timer should start when menu closes or dragging stops
if (intentToStartEditTime && meta !== null && meta !== void 0 && meta.shouldStartTimer && !shouldPersistActiveSession) {
timer.startTimer();
}
if (hasDocChanges) {
timer.startTimer();
if ((0, _shouldSkipTr.shouldSkipTr)(tr)) {
return _objectSpread(_objectSpread({}, pluginState), {}, {
shouldPersistActiveSession: shouldPersistActiveSession
});
}
var newPluginState = (0, _getNewPluginState.getNewPluginState)({
now: now,
intentToStartEditTime: intentToStartEditTime,
shouldPersistActiveSession: shouldPersistActiveSession,
tr: tr,
pluginState: pluginState,
oldState: oldState,
newState: newState
});
return newPluginState;
}
return _objectSpread(_objectSpread({}, pluginState), {}, {
lastSelection: (meta === null || meta === void 0 ? void 0 : meta.newSelection) || pluginState.lastSelection,
intentToStartEditTime: intentToStartEditTime,
shouldPersistActiveSession: shouldPersistActiveSession
});
}
},
view: function view(_view) {
var fireAnalyticsEvent = function fireAnalyticsEvent() {
var pluginState = metricsKey.getState(_view.state);
if (!pluginState) {
return;
}
var toolbarDocking;
if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_controls', 'cohort', 'variant1')) {
toolbarDocking = userPreferencesProvider === null || userPreferencesProvider === void 0 ? void 0 : userPreferencesProvider.getPreference('toolbarDockingInitialPosition');
}
var payloadToSend = (0, _analytics.getAnalyticsPayload)({
currentContent: _view.state.doc.content,
pluginState: pluginState,
toolbarDocking: toolbarDocking || undefined
});
if (pluginState && pluginState.totalActionCount > 0 && pluginState.activeSessionTime > 0) {
var _api$analytics;
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent(payloadToSend, undefined, {
immediate: true
});
}
};
var unbindBeforeUnload = (0, _bindEventListener.bind)(window, {
type: 'beforeunload',
listener: function listener() {
fireAnalyticsEvent();
}
});
return {
destroy: function destroy() {
fireAnalyticsEvent();
timer.cleanupTimer();
unbindBeforeUnload();
}
};
},
props: {
handleDOMEvents: {
click: function click(view) {
var _pluginState$lastSele, _pluginState$lastSele2;
var newSelection = view.state.tr.selection;
var pluginState = api === null || api === void 0 ? void 0 : api.metrics.sharedState.currentState();
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) {
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.metrics.commands.handleIntentToStartEdit({
newSelection: newSelection
}));
}
return false;
}
}
}
});
};