@atlaskit/editor-plugin-interactivity
Version:
Interactivity plugin for @atlaskit/editor-core
125 lines (118 loc) • 5.74 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.InteractionTracker = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _boundedMap = require("../collections/bounded-map");
var _interactionEvents = require("./interaction-events");
/** Optional so a `PerformanceEntry` is assignable without a cast: the DOM typings lack the field. */
/** Entries of one interaction arrive within it, so older than the last few hundred is not needed. */
var MAX_TRACKED = 256;
/**
* Makes interactions out of what the observer reports, for one session. Entries sharing a non-zero
* `interactionId` — the browser's own definition of an interaction, the one INP filters on — are one
* interaction whose latency is the maximum `duration` among them. They arrive incrementally, so a
* latency can grow after it was first reported, and callers move what they counted rather than
* counting the interaction twice.
*
* The editor's events answer what an entry cannot: which interactions were the editor's, and how
* many there were, including the ones below the Event Timing reporting threshold.
*/
var InteractionTracker = exports.InteractionTracker = /*#__PURE__*/function () {
/**
* Both arguments keep the interactions of the previous session out of this one.
*
* @param startsAfterInteractionId the highest id the previous tracker saw. Without it, an entry
* still arriving for that session's interaction would look new here and be counted twice.
* @param startedAt when the session opened. No id can keep out an interaction started before the
* first session of a page: Event Timing produces the entry after the event was presented, so the
* click on Edit that mounted the editor reaches an observer which subscribed while its handler
* ran. The page count the session started from has already counted it.
*/
function InteractionTracker() {
var startsAfterInteractionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var startedAt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
(0, _classCallCheck2.default)(this, InteractionTracker);
(0, _defineProperty2.default)(this, "interactions", new _boundedMap.BoundedMap(MAX_TRACKED));
(0, _defineProperty2.default)(this, "groupByEvent", new _boundedMap.BoundedMap(MAX_TRACKED));
(0, _defineProperty2.default)(this, "highestInteractionId", 0);
this.startsAfterInteractionId = startsAfterInteractionId;
this.startedAt = startedAt;
}
return (0, _createClass2.default)(InteractionTracker, [{
key: "lastInteractionId",
get: function get() {
return Math.max(this.highestInteractionId, this.startsAfterInteractionId);
}
/**
* Merges an entry into the interaction it belongs to.
*
* @returns what that changed, or nothing when the entry belongs to no interaction of this
* session or left the latency as it was.
*/
}, {
key: "merge",
value: function merge(entry) {
if (!Number.isFinite(entry.duration) || entry.duration < 0) {
return undefined;
}
var interactionId = entry.interactionId;
if (!interactionId) {
return undefined;
}
// Neither check covers the other: an entry is dated by its own event rather than by the
// interaction, so the `keyup` of a press that rotated the session is dated after the
// rotation, and the click that mounted the editor has no id to recognise it by.
if (interactionId <= this.startsAfterInteractionId || entry.startTime < this.startedAt) {
return undefined;
}
this.highestInteractionId = Math.max(this.highestInteractionId, interactionId);
var tracked = this.interactions.get(interactionId);
if (tracked === undefined) {
// Taken once: an entry that only makes the interaction slower has to move its count
// within the group it was counted in, not into another one.
var group = this.groupByEvent.get((0, _interactionEvents.eventKey)(entry.name, entry.startTime));
var interaction = {
group: group,
latencyMs: entry.duration
};
this.interactions.set(interactionId, interaction);
return {
type: 'new',
interactionId: interactionId,
latencyMs: interaction.latencyMs,
group: group
};
}
// Not the slowest entry of the interaction, so its latency stands.
if (entry.duration <= tracked.latencyMs) {
return undefined;
}
var previousLatencyMs = tracked.latencyMs;
tracked.latencyMs = entry.duration;
return {
type: 'remeasured',
interactionId: interactionId,
previousLatencyMs: previousLatencyMs,
latencyMs: tracked.latencyMs,
group: tracked.group
};
}
}, {
key: "recordEditorEvent",
value: function recordEditorEvent(event) {
var kind = (0, _interactionEvents.interactionEventKind)(event.type);
if (!kind) {
return undefined;
}
// Every event of the interaction, because any of them can be the one Event Timing reports
// as the slowest: for a pointer press that is usually the click.
this.groupByEvent.set((0, _interactionEvents.eventKey)(event.type, event.timeStamp), kind.group);
return kind.counts ? kind.group : undefined;
}
}]);
}();