UNPKG

@atlaskit/editor-plugin-metrics

Version:

Metrics plugin for @atlaskit/editor-core

167 lines (163 loc) 8.65 kB
"use strict"; 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; } } } }); };