@wordpress/core-data 7.39.1-next.v.0 → 7.39.1-next.v.202602091733.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/build/awareness/awareness-state.cjs +267 -0
- package/build/awareness/awareness-state.cjs.map +7 -0
- package/build/awareness/base-awareness.cjs +14 -11
- package/build/awareness/base-awareness.cjs.map +2 -2
- package/build/awareness/config.cjs +5 -2
- package/build/awareness/config.cjs.map +2 -2
- package/build/awareness/post-editor-awareness.cjs +9 -9
- package/build/awareness/post-editor-awareness.cjs.map +2 -2
- package/build/awareness/typed-awareness.cjs +56 -0
- package/build/awareness/typed-awareness.cjs.map +7 -0
- package/build/awareness/types.cjs.map +1 -1
- package/build/awareness/utils.cjs +43 -14
- package/build/awareness/utils.cjs.map +2 -2
- package/build/entities.cjs +1 -1
- package/build/entities.cjs.map +1 -1
- package/build/hooks/use-post-editor-awareness-state.cjs +11 -11
- package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
- package/build/index.cjs +2 -0
- package/build/index.cjs.map +2 -2
- package/build/private-apis.cjs +3 -1
- package/build/private-apis.cjs.map +2 -2
- package/build/sync.cjs +18 -6
- package/build/sync.cjs.map +3 -3
- package/build/utils/crdt-blocks.cjs +3 -2
- package/build/utils/crdt-blocks.cjs.map +3 -3
- package/build/utils/crdt-user-selections.cjs +2 -1
- package/build/utils/crdt-user-selections.cjs.map +3 -3
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/awareness/awareness-state.mjs +242 -0
- package/build-module/awareness/awareness-state.mjs.map +7 -0
- package/build-module/awareness/base-awareness.mjs +14 -11
- package/build-module/awareness/base-awareness.mjs.map +2 -2
- package/build-module/awareness/config.mjs +3 -1
- package/build-module/awareness/config.mjs.map +2 -2
- package/build-module/awareness/post-editor-awareness.mjs +9 -9
- package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
- package/build-module/awareness/typed-awareness.mjs +31 -0
- package/build-module/awareness/typed-awareness.mjs.map +7 -0
- package/build-module/awareness/utils.mjs +38 -12
- package/build-module/awareness/utils.mjs.map +2 -2
- package/build-module/entities.mjs +1 -1
- package/build-module/entities.mjs.map +1 -1
- package/build-module/hooks/use-post-editor-awareness-state.mjs +10 -10
- package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
- package/build-module/index.mjs +1 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/private-apis.mjs +3 -1
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/sync.mjs +9 -3
- package/build-module/sync.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +2 -1
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-user-selections.mjs +2 -1
- package/build-module/utils/crdt-user-selections.mjs.map +2 -2
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/awareness/awareness-state.d.ts +125 -0
- package/build-types/awareness/awareness-state.d.ts.map +1 -0
- package/build-types/awareness/base-awareness.d.ts +9 -6
- package/build-types/awareness/base-awareness.d.ts.map +1 -1
- package/build-types/awareness/config.d.ts +4 -0
- package/build-types/awareness/config.d.ts.map +1 -1
- package/build-types/awareness/post-editor-awareness.d.ts +4 -4
- package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
- package/build-types/awareness/typed-awareness.d.ts +25 -0
- package/build-types/awareness/typed-awareness.d.ts.map +1 -0
- package/build-types/awareness/types.d.ts +19 -10
- package/build-types/awareness/types.d.ts.map +1 -1
- package/build-types/awareness/utils.d.ts +14 -11
- package/build-types/awareness/utils.d.ts.map +1 -1
- package/build-types/hooks/use-post-editor-awareness-state.d.ts +6 -6
- package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/sync.d.ts +3 -2
- package/build-types/sync.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-user-selections.d.ts +1 -1
- package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts +1 -2
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/package.json +18 -18
- package/src/awareness/awareness-state.ts +342 -0
- package/src/awareness/base-awareness.ts +14 -11
- package/src/awareness/config.ts +5 -0
- package/src/awareness/post-editor-awareness.ts +11 -11
- package/src/awareness/typed-awareness.ts +44 -0
- package/src/awareness/types.ts +25 -11
- package/src/awareness/utils.ts +67 -27
- package/src/entities.js +1 -1
- package/src/hooks/use-post-editor-awareness-state.ts +21 -20
- package/src/index.js +1 -0
- package/src/private-apis.js +2 -0
- package/src/sync.ts +14 -3
- package/src/utils/crdt-blocks.ts +2 -1
- package/src/utils/crdt-user-selections.ts +3 -2
- package/src/utils/crdt.ts +1 -2
- package/src/utils/test/crdt.ts +5 -5
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/core-data/src/awareness/awareness-state.ts
|
|
21
|
+
var awareness_state_exports = {};
|
|
22
|
+
__export(awareness_state_exports, {
|
|
23
|
+
AwarenessState: () => AwarenessState
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(awareness_state_exports);
|
|
26
|
+
var import_config = require("./config.cjs");
|
|
27
|
+
var import_typed_awareness = require("./typed-awareness.cjs");
|
|
28
|
+
var import_utils = require("./utils.cjs");
|
|
29
|
+
var AwarenessWithEqualityChecks = class extends import_typed_awareness.TypedAwareness {
|
|
30
|
+
/** OVERRIDDEN METHODS */
|
|
31
|
+
/**
|
|
32
|
+
* Set a local state field on an awareness document. Calling this method may
|
|
33
|
+
* trigger rerenders of any subscribed components.
|
|
34
|
+
*
|
|
35
|
+
* Equality checks are provided by the abstract `equalityFieldChecks` property.
|
|
36
|
+
* @param field - The field to set.
|
|
37
|
+
* @param value - The value to set.
|
|
38
|
+
*/
|
|
39
|
+
setLocalStateField(field, value) {
|
|
40
|
+
if (this.isFieldEqual(
|
|
41
|
+
field,
|
|
42
|
+
value,
|
|
43
|
+
this.getLocalStateField(field) ?? void 0
|
|
44
|
+
)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
super.setLocalStateField(field, value);
|
|
48
|
+
}
|
|
49
|
+
/** CUSTOM METHODS */
|
|
50
|
+
/**
|
|
51
|
+
* Determine if a field value has changed using the provided equality checks.
|
|
52
|
+
* @param field - The field to check.
|
|
53
|
+
* @param value1 - The first value to compare.
|
|
54
|
+
* @param value2 - The second value to compare.
|
|
55
|
+
*/
|
|
56
|
+
isFieldEqual(field, value1, value2) {
|
|
57
|
+
if (["clientId", "isConnected", "isMe"].includes(field)) {
|
|
58
|
+
return value1 === value2;
|
|
59
|
+
}
|
|
60
|
+
if (field in this.equalityFieldChecks) {
|
|
61
|
+
const fn = this.equalityFieldChecks[field];
|
|
62
|
+
return fn(value1, value2);
|
|
63
|
+
}
|
|
64
|
+
throw new Error(
|
|
65
|
+
`No equality check implemented for awareness state field "${field.toString()}".`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Determine if two states are equal by comparing each field using the
|
|
70
|
+
* provided equality checks.
|
|
71
|
+
* @param state1 - The first state to compare.
|
|
72
|
+
* @param state2 - The second state to compare.
|
|
73
|
+
*/
|
|
74
|
+
isStateEqual(state1, state2) {
|
|
75
|
+
return [
|
|
76
|
+
.../* @__PURE__ */ new Set([
|
|
77
|
+
...(0, import_utils.getTypedKeys)(state1),
|
|
78
|
+
...(0, import_utils.getTypedKeys)(state2)
|
|
79
|
+
])
|
|
80
|
+
].every((field) => {
|
|
81
|
+
const value1 = state1[field];
|
|
82
|
+
const value2 = state2[field];
|
|
83
|
+
return this.isFieldEqual(field, value1, value2);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var AwarenessState = class extends AwarenessWithEqualityChecks {
|
|
88
|
+
/** CUSTOM PROPERTIES */
|
|
89
|
+
/**
|
|
90
|
+
* Whether the setUp method has been called, to avoid running it multiple
|
|
91
|
+
* times.
|
|
92
|
+
*/
|
|
93
|
+
hasSetupRun = false;
|
|
94
|
+
/**
|
|
95
|
+
* We keep track of all seen states during the current session for two reasons:
|
|
96
|
+
*
|
|
97
|
+
* 1. So that we can represent recently disconnected collaborators in our UI, even
|
|
98
|
+
* after they have been removed from the awareness document.
|
|
99
|
+
* 2. So that we can provide debug information about all collaborators seen during
|
|
100
|
+
* the session.
|
|
101
|
+
*/
|
|
102
|
+
disconnectedCollaborators = /* @__PURE__ */ new Set();
|
|
103
|
+
seenStates = /* @__PURE__ */ new Map();
|
|
104
|
+
/**
|
|
105
|
+
* Hold a snapshot of the previous awareness state allows us to compare the
|
|
106
|
+
* state values and avoid unnecessary updates to subscribers.
|
|
107
|
+
*/
|
|
108
|
+
previousSnapshot = /* @__PURE__ */ new Map();
|
|
109
|
+
stateSubscriptions = [];
|
|
110
|
+
/**
|
|
111
|
+
* In some cases, we may want to throttle setting local state fields to avoid
|
|
112
|
+
* overwhelming the awareness document with rapid updates. At the same time, we
|
|
113
|
+
* want to ensure that when we read our own state locally, we get the latest
|
|
114
|
+
* value -- even if it hasn't yet been set on the awareness instance.
|
|
115
|
+
*/
|
|
116
|
+
myThrottledState = {};
|
|
117
|
+
throttleTimeouts = /* @__PURE__ */ new Map();
|
|
118
|
+
/** CUSTOM METHODS */
|
|
119
|
+
/**
|
|
120
|
+
* Set up the awareness state. This method is idempotent and will only run
|
|
121
|
+
* once. Subclasses should override `onSetUp()` instead of this method to
|
|
122
|
+
* add their own setup logic.
|
|
123
|
+
*
|
|
124
|
+
* This is defined as a readonly arrow function property to prevent
|
|
125
|
+
* subclasses from overriding it.
|
|
126
|
+
*/
|
|
127
|
+
setUp = () => {
|
|
128
|
+
if (this.hasSetupRun) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.hasSetupRun = true;
|
|
132
|
+
this.onSetUp();
|
|
133
|
+
this.on(
|
|
134
|
+
"change",
|
|
135
|
+
({ added, removed, updated }) => {
|
|
136
|
+
[...added, ...updated].forEach((id) => {
|
|
137
|
+
this.disconnectedCollaborators.delete(id);
|
|
138
|
+
});
|
|
139
|
+
removed.forEach((id) => {
|
|
140
|
+
this.disconnectedCollaborators.add(id);
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
this.disconnectedCollaborators.delete(id);
|
|
143
|
+
this.updateSubscribers(
|
|
144
|
+
true
|
|
145
|
+
/* force update */
|
|
146
|
+
);
|
|
147
|
+
}, import_config.REMOVAL_DELAY_IN_MS);
|
|
148
|
+
});
|
|
149
|
+
this.updateSubscribers();
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Get the most recent state from the last processed change event.
|
|
155
|
+
*
|
|
156
|
+
* @return An array of EnhancedState< State >.
|
|
157
|
+
*/
|
|
158
|
+
getCurrentState() {
|
|
159
|
+
return Array.from(this.previousSnapshot.values());
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get all seen states in this session to enable debug reporting.
|
|
163
|
+
*/
|
|
164
|
+
getSeenStates() {
|
|
165
|
+
return this.seenStates;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Allow external code to subscribe to awareness state changes.
|
|
169
|
+
* @param callback - The callback to subscribe to.
|
|
170
|
+
*/
|
|
171
|
+
onStateChange(callback) {
|
|
172
|
+
this.stateSubscriptions.push(callback);
|
|
173
|
+
return () => {
|
|
174
|
+
this.stateSubscriptions = this.stateSubscriptions.filter(
|
|
175
|
+
(cb) => cb !== callback
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Set a local state field on an awareness document with throttle. See caveats
|
|
181
|
+
* of this.setLocalStateField.
|
|
182
|
+
* @param field - The field to set.
|
|
183
|
+
* @param value - The value to set.
|
|
184
|
+
* @param wait - The wait time in milliseconds.
|
|
185
|
+
*/
|
|
186
|
+
setThrottledLocalStateField(field, value, wait) {
|
|
187
|
+
this.setLocalStateField(field, value);
|
|
188
|
+
this.throttleTimeouts.set(
|
|
189
|
+
field,
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
this.throttleTimeouts.delete(field);
|
|
192
|
+
if (this.myThrottledState[field]) {
|
|
193
|
+
this.setLocalStateField(
|
|
194
|
+
field,
|
|
195
|
+
this.myThrottledState[field]
|
|
196
|
+
);
|
|
197
|
+
delete this.myThrottledState[field];
|
|
198
|
+
}
|
|
199
|
+
}, wait)
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Set the current collaborator's connection status as awareness state.
|
|
204
|
+
* @param isConnected - The connection status.
|
|
205
|
+
*/
|
|
206
|
+
setConnectionStatus(isConnected) {
|
|
207
|
+
if (isConnected) {
|
|
208
|
+
this.disconnectedCollaborators.delete(this.clientID);
|
|
209
|
+
} else {
|
|
210
|
+
this.disconnectedCollaborators.add(this.clientID);
|
|
211
|
+
}
|
|
212
|
+
this.updateSubscribers(
|
|
213
|
+
true
|
|
214
|
+
/* force update */
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Update all subscribed listeners with the latest awareness state.
|
|
219
|
+
* @param forceUpdate - Whether to force an update.
|
|
220
|
+
*/
|
|
221
|
+
updateSubscribers(forceUpdate = false) {
|
|
222
|
+
if (!this.stateSubscriptions.length) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const states = this.getStates();
|
|
226
|
+
this.seenStates = new Map([
|
|
227
|
+
...this.seenStates.entries(),
|
|
228
|
+
...states.entries()
|
|
229
|
+
]);
|
|
230
|
+
const updatedStates = new Map(
|
|
231
|
+
[...this.disconnectedCollaborators, ...states.keys()].filter((clientId) => {
|
|
232
|
+
return Object.keys(this.seenStates.get(clientId) ?? {}).length > 0;
|
|
233
|
+
}).map((clientId) => {
|
|
234
|
+
const rawState = this.seenStates.get(clientId);
|
|
235
|
+
const isConnected = !this.disconnectedCollaborators.has(clientId);
|
|
236
|
+
const isMe = clientId === this.clientID;
|
|
237
|
+
const myState = isMe ? this.myThrottledState : {};
|
|
238
|
+
const state = {
|
|
239
|
+
...rawState,
|
|
240
|
+
...myState,
|
|
241
|
+
clientId,
|
|
242
|
+
isConnected,
|
|
243
|
+
isMe
|
|
244
|
+
};
|
|
245
|
+
return [clientId, state];
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
if (!forceUpdate) {
|
|
249
|
+
if ((0, import_utils.areMapsEqual)(
|
|
250
|
+
this.previousSnapshot,
|
|
251
|
+
updatedStates,
|
|
252
|
+
this.isStateEqual.bind(this)
|
|
253
|
+
)) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
this.previousSnapshot = updatedStates;
|
|
258
|
+
this.stateSubscriptions.forEach((callback) => {
|
|
259
|
+
callback(Array.from(updatedStates.values()));
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
264
|
+
0 && (module.exports = {
|
|
265
|
+
AwarenessState
|
|
266
|
+
});
|
|
267
|
+
//# sourceMappingURL=awareness-state.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/awareness/awareness-state.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Internal dependencies\n */\nimport { REMOVAL_DELAY_IN_MS } from './config';\nimport { TypedAwareness } from './typed-awareness';\nimport type { EnhancedState, EqualityFieldCheck } from './types';\nimport { getTypedKeys, areMapsEqual } from './utils';\n\ntype AwarenessClientID = number;\n\ninterface AwarenessStateChange {\n\tadded: AwarenessClientID[];\n\tupdated: AwarenessClientID[];\n\tremoved: AwarenessClientID[];\n}\n\nabstract class AwarenessWithEqualityChecks<\n\tState extends object,\n> extends TypedAwareness< State > {\n\t/** OVERRIDDEN METHODS */\n\n\t/**\n\t * Set a local state field on an awareness document. Calling this method may\n\t * trigger rerenders of any subscribed components.\n\t *\n\t * Equality checks are provided by the abstract `equalityFieldChecks` property.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t */\n\tpublic setLocalStateField< FieldName extends string & keyof State >(\n\t\tfield: FieldName,\n\t\tvalue: State[ FieldName ]\n\t): void {\n\t\tif (\n\t\t\tthis.isFieldEqual(\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tthis.getLocalStateField( field ) ?? undefined\n\t\t\t)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.setLocalStateField( field, value );\n\t}\n\n\t/** ABSTRACT PROPERTIES */\n\n\t/**\n\t * Extending classes must implement equality checks for each awareness state\n\t * field they manage.\n\t */\n\tprotected abstract equalityFieldChecks: {\n\t\t[ FieldName in keyof State ]: EqualityFieldCheck< State, FieldName >;\n\t};\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Determine if a field value has changed using the provided equality checks.\n\t * @param field - The field to check.\n\t * @param value1 - The first value to compare.\n\t * @param value2 - The second value to compare.\n\t */\n\tprotected isFieldEqual< FieldName extends keyof State >(\n\t\tfield: FieldName,\n\t\tvalue1?: State[ FieldName ],\n\t\tvalue2?: State[ FieldName ]\n\t): boolean {\n\t\tif (\n\t\t\t[ 'clientId', 'isConnected', 'isMe' ].includes( field as string )\n\t\t) {\n\t\t\treturn value1 === value2;\n\t\t}\n\n\t\tif ( field in this.equalityFieldChecks ) {\n\t\t\tconst fn = this.equalityFieldChecks[ field ];\n\t\t\treturn fn( value1, value2 );\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No equality check implemented for awareness state field \"${ field.toString() }\".`\n\t\t);\n\t}\n\n\t/**\n\t * Determine if two states are equal by comparing each field using the\n\t * provided equality checks.\n\t * @param state1 - The first state to compare.\n\t * @param state2 - The second state to compare.\n\t */\n\tprotected isStateEqual( state1: State, state2: State ): boolean {\n\t\treturn [\n\t\t\t...new Set< keyof State >( [\n\t\t\t\t...getTypedKeys( state1 ),\n\t\t\t\t...getTypedKeys( state2 ),\n\t\t\t] ),\n\t\t].every( ( field ) => {\n\t\t\tconst value1 = state1[ field ];\n\t\t\tconst value2 = state2[ field ];\n\n\t\t\treturn this.isFieldEqual( field, value1, value2 );\n\t\t} );\n\t}\n}\n\n/**\n * Abstract class to manage awareness and allow external code to subscribe to\n * state updates.\n */\nexport abstract class AwarenessState<\n\tState extends object = {},\n> extends AwarenessWithEqualityChecks< State > {\n\t/** CUSTOM PROPERTIES */\n\n\t/**\n\t * Whether the setUp method has been called, to avoid running it multiple\n\t * times.\n\t */\n\tprivate hasSetupRun = false;\n\n\t/**\n\t * We keep track of all seen states during the current session for two reasons:\n\t *\n\t * 1. So that we can represent recently disconnected collaborators in our UI, even\n\t * after they have been removed from the awareness document.\n\t * 2. So that we can provide debug information about all collaborators seen during\n\t * the session.\n\t */\n\tprivate disconnectedCollaborators: Set< number > = new Set();\n\tprivate seenStates: Map< number, State > = new Map();\n\n\t/**\n\t * Hold a snapshot of the previous awareness state allows us to compare the\n\t * state values and avoid unnecessary updates to subscribers.\n\t */\n\tprivate previousSnapshot = new Map< number, EnhancedState< State > >();\n\tprivate stateSubscriptions: Array<\n\t\t( newState: EnhancedState< State >[] ) => void\n\t> = [];\n\n\t/**\n\t * In some cases, we may want to throttle setting local state fields to avoid\n\t * overwhelming the awareness document with rapid updates. At the same time, we\n\t * want to ensure that when we read our own state locally, we get the latest\n\t * value -- even if it hasn't yet been set on the awareness instance.\n\t */\n\tprivate myThrottledState: Partial< State > = {};\n\tprivate throttleTimeouts: Map< string, NodeJS.Timeout > = new Map();\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Set up the awareness state. This method is idempotent and will only run\n\t * once. Subclasses should override `onSetUp()` instead of this method to\n\t * add their own setup logic.\n\t *\n\t * This is defined as a readonly arrow function property to prevent\n\t * subclasses from overriding it.\n\t */\n\tpublic readonly setUp = (): void => {\n\t\tif ( this.hasSetupRun ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.hasSetupRun = true;\n\n\t\tthis.onSetUp();\n\n\t\tthis.on(\n\t\t\t'change',\n\t\t\t( { added, removed, updated }: AwarenessStateChange ) => {\n\t\t\t\t[ ...added, ...updated ].forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t} );\n\n\t\t\t\tremoved.forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.add( id );\n\n\t\t\t\t\tsetTimeout( () => {\n\t\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t\t\tthis.updateSubscribers( true /* force update */ );\n\t\t\t\t\t}, REMOVAL_DELAY_IN_MS );\n\t\t\t\t} );\n\n\t\t\t\t// Do not force-update the store here, since this change handler can be\n\t\t\t\t// called even when there are no actual state changes.\n\t\t\t\tthis.updateSubscribers();\n\t\t\t}\n\t\t);\n\t};\n\n\t/**\n\t * Hook method for subclasses to add their own setup logic. This is called\n\t * once after the base class setup completes. All subclasses must implement\n\t * this method. If extending a class that already implements `onSetUp()`,\n\t * call `super.onSetUp()` to ensure parent setup runs.\n\t */\n\tprotected abstract onSetUp(): void;\n\n\t/**\n\t * Get the most recent state from the last processed change event.\n\t *\n\t * @return An array of EnhancedState< State >.\n\t */\n\tpublic getCurrentState(): EnhancedState< State >[] {\n\t\treturn Array.from( this.previousSnapshot.values() );\n\t}\n\n\t/**\n\t * Get all seen states in this session to enable debug reporting.\n\t */\n\tpublic getSeenStates(): Map< number, State > {\n\t\treturn this.seenStates;\n\t}\n\n\t/**\n\t * Allow external code to subscribe to awareness state changes.\n\t * @param callback - The callback to subscribe to.\n\t */\n\tpublic onStateChange(\n\t\tcallback: ( newState: EnhancedState< State >[] ) => void\n\t): () => void {\n\t\tthis.stateSubscriptions.push( callback );\n\n\t\treturn () => {\n\t\t\tthis.stateSubscriptions = this.stateSubscriptions.filter(\n\t\t\t\t( cb ) => cb !== callback\n\t\t\t);\n\t\t};\n\t}\n\n\t/**\n\t * Set a local state field on an awareness document with throttle. See caveats\n\t * of this.setLocalStateField.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t * @param wait - The wait time in milliseconds.\n\t */\n\tpublic setThrottledLocalStateField<\n\t\tFieldName extends string & keyof State,\n\t>( field: FieldName, value: State[ FieldName ], wait: number ): void {\n\t\tthis.setLocalStateField( field, value );\n\n\t\tthis.throttleTimeouts.set(\n\t\t\tfield,\n\t\t\tsetTimeout( () => {\n\t\t\t\tthis.throttleTimeouts.delete( field );\n\t\t\t\tif ( this.myThrottledState[ field ] ) {\n\t\t\t\t\tthis.setLocalStateField(\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tthis.myThrottledState[ field ]\n\t\t\t\t\t);\n\n\t\t\t\t\tdelete this.myThrottledState[ field ];\n\t\t\t\t}\n\t\t\t}, wait )\n\t\t);\n\t}\n\n\t/**\n\t * Set the current collaborator's connection status as awareness state.\n\t * @param isConnected - The connection status.\n\t */\n\tpublic setConnectionStatus( isConnected: boolean ): void {\n\t\tif ( isConnected ) {\n\t\t\tthis.disconnectedCollaborators.delete( this.clientID );\n\t\t} else {\n\t\t\tthis.disconnectedCollaborators.add( this.clientID );\n\t\t}\n\n\t\tthis.updateSubscribers( true /* force update */ );\n\t}\n\n\t/**\n\t * Update all subscribed listeners with the latest awareness state.\n\t * @param forceUpdate - Whether to force an update.\n\t */\n\tprotected updateSubscribers( forceUpdate = false ): void {\n\t\tif ( ! this.stateSubscriptions.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst states = this.getStates();\n\n\t\tthis.seenStates = new Map< number, State >( [\n\t\t\t...this.seenStates.entries(),\n\t\t\t...states.entries(),\n\t\t] );\n\n\t\tconst updatedStates = new Map< number, EnhancedState< State > >(\n\t\t\t[ ...this.disconnectedCollaborators, ...states.keys() ]\n\t\t\t\t.filter( ( clientId ) => {\n\t\t\t\t\t// Exclude any collaborators with empty awareness state. This can happen from\n\t\t\t\t\t// the Yjs inspector.\n\t\t\t\t\treturn (\n\t\t\t\t\t\tObject.keys( this.seenStates.get( clientId ) ?? {} )\n\t\t\t\t\t\t\t.length > 0\n\t\t\t\t\t);\n\t\t\t\t} )\n\t\t\t\t.map( ( clientId ) => {\n\t\t\t\t\t// The filter above ensures that seenStates has the clientId.\n\t\t\t\t\tconst rawState: State = this.seenStates.get( clientId )!;\n\n\t\t\t\t\tconst isConnected =\n\t\t\t\t\t\t! this.disconnectedCollaborators.has( clientId );\n\t\t\t\t\tconst isMe = clientId === this.clientID;\n\t\t\t\t\tconst myState: Partial< State > = isMe\n\t\t\t\t\t\t? this.myThrottledState\n\t\t\t\t\t\t: {};\n\t\t\t\t\tconst state: EnhancedState< State > = {\n\t\t\t\t\t\t...rawState,\n\t\t\t\t\t\t...myState,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t\tisConnected,\n\t\t\t\t\t\tisMe,\n\t\t\t\t\t};\n\n\t\t\t\t\treturn [ clientId, state ];\n\t\t\t\t} )\n\t\t);\n\n\t\tif ( ! forceUpdate ) {\n\t\t\tif (\n\t\t\t\tareMapsEqual(\n\t\t\t\t\tthis.previousSnapshot,\n\t\t\t\t\tupdatedStates,\n\t\t\t\t\tthis.isStateEqual.bind( this )\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// Awareness state unchanged, do not update subscribers.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Update subscribers.\n\t\tthis.previousSnapshot = updatedStates;\n\t\tthis.stateSubscriptions.forEach( ( callback ) => {\n\t\t\tcallback( Array.from( updatedStates.values() ) );\n\t\t} );\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -26,28 +26,31 @@ __export(base_awareness_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(base_awareness_exports);
|
|
28
28
|
var import_data = require("@wordpress/data");
|
|
29
|
-
var
|
|
29
|
+
var import_awareness_state = require("./awareness-state.cjs");
|
|
30
30
|
var import_name = require("../name.cjs");
|
|
31
31
|
var import_utils = require("./utils.cjs");
|
|
32
|
-
var BaseAwarenessState = class extends
|
|
32
|
+
var BaseAwarenessState = class extends import_awareness_state.AwarenessState {
|
|
33
33
|
onSetUp() {
|
|
34
|
-
void this.
|
|
34
|
+
void this.setCurrentCollaboratorInfo();
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Set the current
|
|
37
|
+
* Set the current collaborator info in the local state.
|
|
38
38
|
*/
|
|
39
|
-
async
|
|
39
|
+
async setCurrentCollaboratorInfo() {
|
|
40
40
|
const states = this.getStates();
|
|
41
|
-
const
|
|
42
|
-
([clientId, state]) => state.
|
|
43
|
-
).map(([, state]) => state.
|
|
41
|
+
const otherCollaboratorColors = Array.from(states.entries()).filter(
|
|
42
|
+
([clientId, state]) => state.collaboratorInfo && clientId !== this.clientID
|
|
43
|
+
).map(([, state]) => state.collaboratorInfo.color).filter(Boolean);
|
|
44
44
|
const currentUser = await (0, import_data.resolveSelect)(import_name.STORE_NAME).getCurrentUser();
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const collaboratorInfo = (0, import_utils.generateCollaboratorInfo)(
|
|
46
|
+
currentUser,
|
|
47
|
+
otherCollaboratorColors
|
|
48
|
+
);
|
|
49
|
+
this.setLocalStateField("collaboratorInfo", collaboratorInfo);
|
|
47
50
|
}
|
|
48
51
|
};
|
|
49
52
|
var baseEqualityFieldChecks = {
|
|
50
|
-
|
|
53
|
+
collaboratorInfo: import_utils.areCollaboratorInfosEqual
|
|
51
54
|
};
|
|
52
55
|
var BaseAwareness = class extends BaseAwarenessState {
|
|
53
56
|
equalityFieldChecks = baseEqualityFieldChecks;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/base-awareness.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { resolveSelect } from '@wordpress/data';\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA8B;
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { resolveSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { AwarenessState } from './awareness-state';\nimport { STORE_NAME as coreStore } from '../name';\nimport { generateCollaboratorInfo, areCollaboratorInfosEqual } from './utils';\n\nimport type { BaseState } from './types';\n\nexport abstract class BaseAwarenessState<\n\tState extends BaseState,\n> extends AwarenessState< State > {\n\tprotected onSetUp(): void {\n\t\tvoid this.setCurrentCollaboratorInfo();\n\t}\n\n\t/**\n\t * Set the current collaborator info in the local state.\n\t */\n\tprivate async setCurrentCollaboratorInfo(): Promise< void > {\n\t\tconst states = this.getStates();\n\t\tconst otherCollaboratorColors = Array.from( states.entries() )\n\t\t\t.filter(\n\t\t\t\t( [ clientId, state ] ) =>\n\t\t\t\t\tstate.collaboratorInfo && clientId !== this.clientID\n\t\t\t)\n\t\t\t.map( ( [ , state ] ) => state.collaboratorInfo.color )\n\t\t\t.filter( Boolean );\n\n\t\t// Get current user info and set it in local state.\n\t\tconst currentUser = await resolveSelect( coreStore ).getCurrentUser();\n\t\tconst collaboratorInfo = generateCollaboratorInfo(\n\t\t\tcurrentUser,\n\t\t\totherCollaboratorColors\n\t\t);\n\t\tthis.setLocalStateField( 'collaboratorInfo', collaboratorInfo );\n\t}\n}\n\nexport const baseEqualityFieldChecks = {\n\tcollaboratorInfo: areCollaboratorInfosEqual,\n};\n\nexport class BaseAwareness extends BaseAwarenessState< BaseState > {\n\tprotected equalityFieldChecks = baseEqualityFieldChecks;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA8B;AAK9B,6BAA+B;AAC/B,kBAAwC;AACxC,mBAAoE;AAI7D,IAAe,qBAAf,cAEG,sCAAwB;AAAA,EACvB,UAAgB;AACzB,SAAK,KAAK,2BAA2B;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,6BAA8C;AAC3D,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,0BAA0B,MAAM,KAAM,OAAO,QAAQ,CAAE,EAC3D;AAAA,MACA,CAAE,CAAE,UAAU,KAAM,MACnB,MAAM,oBAAoB,aAAa,KAAK;AAAA,IAC9C,EACC,IAAK,CAAE,CAAE,EAAE,KAAM,MAAO,MAAM,iBAAiB,KAAM,EACrD,OAAQ,OAAQ;AAGlB,UAAM,cAAc,UAAM,2BAAe,YAAAA,UAAU,EAAE,eAAe;AACpE,UAAM,uBAAmB;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,SAAK,mBAAoB,oBAAoB,gBAAiB;AAAA,EAC/D;AACD;AAEO,IAAM,0BAA0B;AAAA,EACtC,kBAAkB;AACnB;AAEO,IAAM,gBAAN,cAA4B,mBAAgC;AAAA,EACxD,sBAAsB;AACjC;",
|
|
6
6
|
"names": ["coreStore"]
|
|
7
7
|
}
|
|
@@ -21,14 +21,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var config_exports = {};
|
|
22
22
|
__export(config_exports, {
|
|
23
23
|
AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS: () => AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,
|
|
24
|
-
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS: () => LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS
|
|
24
|
+
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS: () => LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,
|
|
25
|
+
REMOVAL_DELAY_IN_MS: () => REMOVAL_DELAY_IN_MS
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(config_exports);
|
|
27
28
|
var AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS = 100;
|
|
28
29
|
var LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS = 5;
|
|
30
|
+
var REMOVAL_DELAY_IN_MS = 5e3;
|
|
29
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
30
32
|
0 && (module.exports = {
|
|
31
33
|
AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,
|
|
32
|
-
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS
|
|
34
|
+
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,
|
|
35
|
+
REMOVAL_DELAY_IN_MS
|
|
33
36
|
});
|
|
34
37
|
//# sourceMappingURL=config.cjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/config.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Delay in milliseconds before throttling the cursor position updates.\n */\nexport const AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS = 100;\n\n/**\n * Delay in milliseconds before updating the cursor position.\n */\nexport const LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS = 5;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAM,yCAAyC;AAK/C,IAAM,qCAAqC;",
|
|
4
|
+
"sourcesContent": ["/**\n * Delay in milliseconds before throttling the cursor position updates.\n */\nexport const AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS = 100;\n\n/**\n * Delay in milliseconds before updating the cursor position.\n */\nexport const LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS = 5;\n\n/**\n * Delay in milliseconds before removing a collaborator from presence indicators.\n */\nexport const REMOVAL_DELAY_IN_MS = 5000;\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAM,yCAAyC;AAK/C,IAAM,qCAAqC;AAK3C,IAAM,sBAAsB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -43,12 +43,12 @@ var PostEditorAwareness = class extends import_base_awareness.BaseAwarenessState
|
|
|
43
43
|
};
|
|
44
44
|
onSetUp() {
|
|
45
45
|
super.onSetUp();
|
|
46
|
-
this.
|
|
46
|
+
this.subscribeToCollaboratorSelectionChanges();
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
* Subscribe to
|
|
49
|
+
* Subscribe to collaborator selection changes and update the selection state.
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
subscribeToCollaboratorSelectionChanges() {
|
|
52
52
|
const {
|
|
53
53
|
getSelectionStart,
|
|
54
54
|
getSelectionEnd,
|
|
@@ -89,7 +89,7 @@ var PostEditorAwareness = class extends import_base_awareness.BaseAwarenessState
|
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
* Update the entity record with the current
|
|
92
|
+
* Update the entity record with the current collaborator's selection.
|
|
93
93
|
*
|
|
94
94
|
* @param selectionStart - The start position of the selection.
|
|
95
95
|
* @param selectionEnd - The end position of the selection.
|
|
@@ -156,13 +156,13 @@ var PostEditorAwareness = class extends import_base_awareness.BaseAwarenessState
|
|
|
156
156
|
value.toJSON()
|
|
157
157
|
])
|
|
158
158
|
);
|
|
159
|
-
const
|
|
159
|
+
const collaboratorMapData = new Map(
|
|
160
160
|
Array.from(this.getSeenStates().entries()).map(
|
|
161
|
-
([clientId,
|
|
161
|
+
([clientId, collaboratorState]) => [
|
|
162
162
|
String(clientId),
|
|
163
163
|
{
|
|
164
|
-
name:
|
|
165
|
-
wpUserId:
|
|
164
|
+
name: collaboratorState.collaboratorInfo.name,
|
|
165
|
+
wpUserId: collaboratorState.collaboratorInfo.id
|
|
166
166
|
}
|
|
167
167
|
]
|
|
168
168
|
)
|
|
@@ -192,7 +192,7 @@ var PostEditorAwareness = class extends import_base_awareness.BaseAwarenessState
|
|
|
192
192
|
return {
|
|
193
193
|
doc: docData,
|
|
194
194
|
clients: serializableClientItems,
|
|
195
|
-
|
|
195
|
+
collaboratorMap: Object.fromEntries(collaboratorMapData)
|
|
196
196
|
};
|
|
197
197
|
}
|
|
198
198
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/post-editor-awareness.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select, subscribe } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-ignore No exported types for block editor store selectors.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwarenessState, baseEqualityFieldChecks } from './base-awareness';\nimport {\n\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,\n\tLOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,\n} from './config';\nimport { STORE_NAME as coreStore } from '../name';\nimport {\n\tareSelectionsStatesEqual,\n\tgetSelectionState,\n} from '../utils/crdt-user-selections';\n\nimport type { SelectionCursor, WPBlockSelection } from '../types';\nimport type {\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA4C;AAC5C,kBAAkB;AAElB,0BAA0C;AAK1C,4BAA4D;AAC5D,oBAGO;AACP,kBAAwC;AACxC,kCAGO;AAWA,IAAM,sBAAN,cAAkC,yCAAsC;AAAA,EAMvE,YACN,KACQ,MACA,MACA,QACP;AACD,UAAO,GAAI;AAJH;AACA;AACA;AAAA,EAGT;AAAA,EAZU,sBAAsB;AAAA,IAC/B,GAAG;AAAA,IACH,aAAa,KAAK;AAAA,EACnB;AAAA,EAWU,UAAgB;AACzB,UAAM,QAAQ;AAEd,SAAK,
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select, subscribe } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-ignore No exported types for block editor store selectors.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwarenessState, baseEqualityFieldChecks } from './base-awareness';\nimport {\n\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,\n\tLOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,\n} from './config';\nimport { STORE_NAME as coreStore } from '../name';\nimport {\n\tareSelectionsStatesEqual,\n\tgetSelectionState,\n} from '../utils/crdt-user-selections';\n\nimport type { SelectionCursor, WPBlockSelection } from '../types';\nimport type {\n\tDebugCollaboratorData,\n\tEditorState,\n\tPostEditorState,\n\tSerializableYItem,\n\tYDocDebugData,\n} from './types';\n\nexport class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {\n\tprotected equalityFieldChecks = {\n\t\t...baseEqualityFieldChecks,\n\t\teditorState: this.areEditorStatesEqual,\n\t};\n\n\tpublic constructor(\n\t\tdoc: Y.Doc,\n\t\tprivate kind: string,\n\t\tprivate name: string,\n\t\tprivate postId: number\n\t) {\n\t\tsuper( doc );\n\t}\n\n\tprotected onSetUp(): void {\n\t\tsuper.onSetUp();\n\n\t\tthis.subscribeToCollaboratorSelectionChanges();\n\t}\n\n\t/**\n\t * Subscribe to collaborator selection changes and update the selection state.\n\t */\n\tprivate subscribeToCollaboratorSelectionChanges(): void {\n\t\tconst {\n\t\t\tgetSelectionStart,\n\t\t\tgetSelectionEnd,\n\t\t\tgetSelectedBlocksInitialCaretPosition,\n\t\t} = select( blockEditorStore );\n\n\t\t// Keep track of the current selection in the outer scope so we can compare\n\t\t// in the subscription.\n\t\tlet selectionStart = getSelectionStart();\n\t\tlet selectionEnd = getSelectionEnd();\n\t\tlet localCursorTimeout: NodeJS.Timeout | null = null;\n\n\t\tsubscribe( () => {\n\t\t\tconst newSelectionStart = getSelectionStart();\n\t\t\tconst newSelectionEnd = getSelectionEnd();\n\n\t\t\tif (\n\t\t\t\tnewSelectionStart === selectionStart &&\n\t\t\t\tnewSelectionEnd === selectionEnd\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tselectionStart = newSelectionStart;\n\t\t\tselectionEnd = newSelectionEnd;\n\n\t\t\t// Typically selection position is only persisted after typing in a block, which\n\t\t\t// can cause selection position to be reset by other users making block updates.\n\t\t\t// Ensure we update the controlled selection right away, persisting our cursor position locally.\n\t\t\tconst initialPosition = getSelectedBlocksInitialCaretPosition();\n\t\t\tvoid this.updateSelectionInEntityRecord(\n\t\t\t\tselectionStart,\n\t\t\t\tselectionEnd,\n\t\t\t\tinitialPosition\n\t\t\t);\n\n\t\t\t// We receive two selection changes in quick succession\n\t\t\t// from local selection events:\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: undefined }\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: 554 }\n\t\t\t// Add a short debounce to avoid sending the first selection change.\n\t\t\tif ( localCursorTimeout ) {\n\t\t\t\tclearTimeout( localCursorTimeout );\n\t\t\t}\n\n\t\t\tlocalCursorTimeout = setTimeout( () => {\n\t\t\t\tconst selectionState = getSelectionState(\n\t\t\t\t\tselectionStart,\n\t\t\t\t\tselectionEnd,\n\t\t\t\t\tthis.doc\n\t\t\t\t);\n\n\t\t\t\tthis.setThrottledLocalStateField(\n\t\t\t\t\t'editorState',\n\t\t\t\t\t{ selection: selectionState },\n\t\t\t\t\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS\n\t\t\t\t);\n\t\t\t}, LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS );\n\t\t} );\n\t}\n\n\t/**\n\t * Update the entity record with the current collaborator's selection.\n\t *\n\t * @param selectionStart - The start position of the selection.\n\t * @param selectionEnd - The end position of the selection.\n\t * @param initialPosition - The initial position of the selection.\n\t */\n\tprivate async updateSelectionInEntityRecord(\n\t\tselectionStart: WPBlockSelection,\n\t\tselectionEnd: WPBlockSelection,\n\t\tinitialPosition: number | null\n\t): Promise< void > {\n\t\t// Send an entityRecord `selection` update if we have a selection.\n\t\t//\n\t\t// Normally WordPress updates the `selection` property of the post when changes are made to blocks.\n\t\t// In a multi-user setup, block changes can occur from other users. When an entity is updated from another\n\t\t// user's changes, useBlockSync() in Gutenberg will reset the user's selection to the last saved selection.\n\t\t//\n\t\t// Manually adding an edit for each movement ensures that other user's changes to the document will\n\t\t// not cause the local user's selection to reset to the last local change location.\n\t\tconst edits = {\n\t\t\tselection: { selectionStart, selectionEnd, initialPosition },\n\t\t};\n\n\t\tconst options = {\n\t\t\tundoIgnore: true,\n\t\t};\n\n\t\t// @ts-ignore Types are not provided when using store name instead of store instance.\n\t\tdispatch( coreStore ).editEntityRecord(\n\t\t\tthis.kind,\n\t\t\tthis.name,\n\t\t\tthis.postId,\n\t\t\tedits,\n\t\t\toptions\n\t\t);\n\t}\n\n\t/**\n\t * Check if two editor states are equal.\n\t *\n\t * @param state1 - The first editor state.\n\t * @param state2 - The second editor state.\n\t * @return True if the editor states are equal, false otherwise.\n\t */\n\tprivate areEditorStatesEqual(\n\t\tstate1?: EditorState,\n\t\tstate2?: EditorState\n\t): boolean {\n\t\tif ( ! state1 || ! state2 ) {\n\t\t\treturn state1 === state2;\n\t\t}\n\n\t\treturn areSelectionsStatesEqual( state1.selection, state2.selection );\n\t}\n\n\t/**\n\t * Get the absolute position index from a selection cursor.\n\t *\n\t * @param selection - The selection cursor.\n\t * @return The absolute position index, or null if not found.\n\t */\n\tpublic getAbsolutePositionIndex(\n\t\tselection: SelectionCursor\n\t): number | null {\n\t\treturn (\n\t\t\tY.createAbsolutePositionFromRelativePosition(\n\t\t\t\tselection.cursorPosition.relativePosition,\n\t\t\t\tthis.doc\n\t\t\t)?.index ?? null\n\t\t);\n\t}\n\n\t/**\n\t * Type guard to check if a struct is a Y.Item (not Y.GC)\n\t * @param struct - The struct to check.\n\t * @return True if the struct is a Y.Item, false otherwise.\n\t */\n\tprivate isYItem( struct: Y.Item | Y.GC ): struct is Y.Item {\n\t\treturn 'content' in struct;\n\t}\n\n\t/**\n\t * Get data for debugging, using the awareness state.\n\t *\n\t * @return {YDocDebugData} The debug data.\n\t */\n\tpublic getDebugData(): YDocDebugData {\n\t\tconst ydoc = this.doc;\n\n\t\t// Manually extract doc data to avoid deprecated toJSON method\n\t\tconst docData: Record< string, unknown > = Object.fromEntries(\n\t\t\tArray.from( ydoc.share, ( [ key, value ] ) => [\n\t\t\t\tkey,\n\t\t\t\tvalue.toJSON(),\n\t\t\t] )\n\t\t);\n\n\t\t// Build collaboratorMap from awareness store (all collaborators seen this session)\n\t\tconst collaboratorMapData = new Map< string, DebugCollaboratorData >(\n\t\t\tArray.from( this.getSeenStates().entries() ).map(\n\t\t\t\t( [ clientId, collaboratorState ] ) => [\n\t\t\t\t\tString( clientId ),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: collaboratorState.collaboratorInfo.name,\n\t\t\t\t\t\twpUserId: collaboratorState.collaboratorInfo.id,\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\n\t\t// Serialize Yjs client items to avoid deep nesting\n\t\tconst serializableClientItems: Record<\n\t\t\tnumber,\n\t\t\tArray< SerializableYItem >\n\t\t> = {};\n\n\t\tydoc.store.clients.forEach( ( structs, clientId ) => {\n\t\t\t// Filter for Y.Item only (skip Y.GC garbage collection structs)\n\t\t\tconst items = structs.filter( this.isYItem );\n\n\t\t\tserializableClientItems[ clientId ] = items.map( ( item ) => {\n\t\t\t\tconst { left, right, ...rest } = item;\n\n\t\t\t\treturn {\n\t\t\t\t\t...rest,\n\t\t\t\t\tleft: left\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: left.id,\n\t\t\t\t\t\t\t\tlength: left.length,\n\t\t\t\t\t\t\t\torigin: left.origin,\n\t\t\t\t\t\t\t\tcontent: left.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t\tright: right\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: right.id,\n\t\t\t\t\t\t\t\tlength: right.length,\n\t\t\t\t\t\t\t\torigin: right.origin,\n\t\t\t\t\t\t\t\tcontent: right.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t};\n\t\t\t} );\n\t\t} );\n\n\t\treturn {\n\t\t\tdoc: docData,\n\t\t\tclients: serializableClientItems,\n\t\t\tcollaboratorMap: Object.fromEntries( collaboratorMapData ),\n\t\t};\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["blockEditorStore", "coreStore"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/core-data/src/awareness/typed-awareness.ts
|
|
21
|
+
var typed_awareness_exports = {};
|
|
22
|
+
__export(typed_awareness_exports, {
|
|
23
|
+
TypedAwareness: () => TypedAwareness
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(typed_awareness_exports);
|
|
26
|
+
var import_sync = require("@wordpress/sync");
|
|
27
|
+
var import_utils = require("./utils.cjs");
|
|
28
|
+
var TypedAwareness = class extends import_sync.Awareness {
|
|
29
|
+
/**
|
|
30
|
+
* Get the states from an awareness document.
|
|
31
|
+
*/
|
|
32
|
+
getStates() {
|
|
33
|
+
return super.getStates();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get a local state field from an awareness document.
|
|
37
|
+
* @param field
|
|
38
|
+
*/
|
|
39
|
+
getLocalStateField(field) {
|
|
40
|
+
const state = this.getLocalState();
|
|
41
|
+
return (0, import_utils.getRecordValue)(state, field);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set a local state field on an awareness document.
|
|
45
|
+
* @param field
|
|
46
|
+
* @param value
|
|
47
|
+
*/
|
|
48
|
+
setLocalStateField(field, value) {
|
|
49
|
+
super.setLocalStateField(field, value);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
53
|
+
0 && (module.exports = {
|
|
54
|
+
TypedAwareness
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=typed-awareness.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/awareness/typed-awareness.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * External dependencies\n */\nimport { Awareness } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { getRecordValue } from './utils';\n\n/**\n * Extended Awareness class with typed state accessors.\n */\nexport class TypedAwareness< State extends object > extends Awareness {\n\t/**\n\t * Get the states from an awareness document.\n\t */\n\tpublic getStates(): Map< number, State > {\n\t\treturn super.getStates() as Map< number, State >;\n\t}\n\n\t/**\n\t * Get a local state field from an awareness document.\n\t * @param field\n\t */\n\tpublic getLocalStateField< FieldName extends keyof State >(\n\t\tfield: FieldName\n\t): State[ FieldName ] | null {\n\t\tconst state: State | null = this.getLocalState() as State | null;\n\t\treturn getRecordValue< State, FieldName >( state, field );\n\t}\n\n\t/**\n\t * Set a local state field on an awareness document.\n\t * @param field\n\t * @param value\n\t */\n\tpublic setLocalStateField< FieldName extends string & keyof State >(\n\t\tfield: FieldName,\n\t\tvalue: State[ FieldName ]\n\t): void {\n\t\tsuper.setLocalStateField( field, value );\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA0B;AAK1B,mBAA+B;AAKxB,IAAM,iBAAN,cAAqD,sBAAU;AAAA;AAAA;AAAA;AAAA,EAI9D,YAAkC;AACxC,WAAO,MAAM,UAAU;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBACN,OAC4B;AAC5B,UAAM,QAAsB,KAAK,cAAc;AAC/C,eAAO,6BAAoC,OAAO,KAAM;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,mBACN,OACA,OACO;AACP,UAAM,mBAAoB,OAAO,KAAM;AAAA,EACxC;AACD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport type {
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport type { Y } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport type { SelectionState } from '../types';\nimport type { User } from '../entity-types';\n\nexport type CollaboratorInfo = Pick<\n\tUser< 'view' >,\n\t'id' | 'name' | 'slug' | 'avatar_urls'\n> & {\n\tbrowserType: string;\n\tcolor: string;\n\tenteredAt: number;\n};\n\n/**\n * This base state represents the presence of the collaborator. We expect it to be\n * extended to include additional state describing the collaborator's current activity.\n * This state must be serializable and compact.\n */\nexport interface BaseState {\n\tcollaboratorInfo: CollaboratorInfo;\n}\n\n/**\n * The editor state includes information about the collaborator's current selection.\n */\nexport interface EditorState {\n\tselection: SelectionState;\n}\n\n/**\n * The post editor state extends the base state with information used to render\n * presence indicators in the post editor.\n */\nexport interface PostEditorState extends BaseState {\n\teditorState?: EditorState;\n}\n\n/**\n * An enhanced state includes additional metadata about the collaborator's connection.\n */\nexport type EnhancedState< State > = State & {\n\tclientId: number;\n\tisConnected: boolean;\n\tisMe: boolean;\n};\n\n/**\n * An enhanced post editor awareness state includes additional metadata about\n * the collaborator and their connection.\n */\nexport type PostEditorAwarenessState = EnhancedState< PostEditorState >;\n\n// WordPress collaborator info for debug export (subset of CollaboratorInfo)\nexport type DebugCollaboratorData = Pick< CollaboratorInfo, 'name' > & {\n\twpUserId: CollaboratorInfo[ 'id' ];\n};\n\nexport interface YDocDebugData {\n\tdoc: Record< string, unknown >;\n\tclients: Record< number, Array< SerializableYItem > >;\n\tcollaboratorMap: Record< string, DebugCollaboratorData >;\n}\n\n// Type for serializable left/right item references to avoid deep nesting\nexport type SerializableYItemRef = Pick<\n\tY.Item,\n\t'id' | 'length' | 'origin' | 'content'\n>;\n\n// Serializable Y.Item - only includes data properties with shallow left/right references\nexport type SerializableYItem = Pick<\n\tY.Item,\n\t| 'id'\n\t| 'length'\n\t| 'origin'\n\t| 'rightOrigin'\n\t| 'parent'\n\t| 'parentSub'\n\t| 'redone'\n\t| 'content'\n\t| 'info'\n> & {\n\tleft: SerializableYItemRef | null;\n\tright: SerializableYItemRef | null;\n};\n\nexport type EqualityFieldCheck< State, FieldName extends keyof State > = (\n\tvalue1?: State[ FieldName ],\n\tvalue2?: State[ FieldName ]\n) => boolean;\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|