@dxos/plugin-space 0.7.1 → 0.7.2-main.f1adc9f

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.
@@ -22,7 +22,7 @@ import { signal } from "@preact/signals-core";
22
22
  import React17 from "react";
23
23
  import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction4, Surface, findPlugin, firstIdInPart, openIds, parseGraphPlugin, parseIntentPlugin as parseIntentPlugin2, parseLayoutPlugin, parseMetadataResolverPlugin, parseNavigationPlugin as parseNavigationPlugin2, resolvePlugin } from "@dxos/app-framework";
24
24
  import { EventSubscriptions } from "@dxos/async";
25
- import { isReactiveObject as isReactiveObject2 } from "@dxos/echo-schema";
25
+ import { isDeleted, isReactiveObject as isReactiveObject2 } from "@dxos/echo-schema";
26
26
  import { scheduledEffect } from "@dxos/echo-signals/core";
27
27
  import { invariant as invariant2 } from "@dxos/invariant";
28
28
  import { LocalStorageStore } from "@dxos/local-storage";
@@ -33,7 +33,7 @@ import { parseClientPlugin } from "@dxos/plugin-client";
33
33
  import { createExtension, memoize as memoize2, toSignal } from "@dxos/plugin-graph";
34
34
  import { ObservabilityAction as ObservabilityAction2 } from "@dxos/plugin-observability/meta";
35
35
  import { PublicKey as PublicKey2 } from "@dxos/react-client";
36
- import { Expando, Filter, SpaceState as SpaceState2, create as create2, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace4, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace2, loadObjectReferences, parseId, FQ_ID_LENGTH } from "@dxos/react-client/echo";
36
+ import { Expando, Filter as Filter2, SpaceState as SpaceState2, create as create2, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace4, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace2, loadObjectReferences, parseId, FQ_ID_LENGTH, SPACE_ID_LENGTH, OBJECT_ID_LENGTH, parseFullyQualifiedId } from "@dxos/react-client/echo";
37
37
  import { osTranslations } from "@dxos/shell/react";
38
38
  import { ComplexMap as ComplexMap2, nonNullable, reduceGroupBy } from "@dxos/util";
39
39
 
@@ -280,7 +280,7 @@ import { create, isReactiveObject, getTypename, getSchema, getObjectAnnotation,
280
280
  import { invariant } from "@dxos/invariant";
281
281
  import { Migrations } from "@dxos/migrations";
282
282
  import { ACTION_TYPE, ACTION_GROUP_TYPE, actionGroupSymbol, getGraph, cleanup, memoize } from "@dxos/plugin-graph";
283
- import { fullyQualifiedId as fullyQualifiedId2, getSpace, isEchoObject, isSpace, SpaceState } from "@dxos/react-client/echo";
283
+ import { fullyQualifiedId as fullyQualifiedId2, getSpace, isEchoObject, isSpace, SpaceState, Filter } from "@dxos/react-client/echo";
284
284
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/util.tsx";
285
285
  var SPACES = `${SPACE_PLUGIN}-spaces`;
286
286
  var SPACE_TYPE = "dxos.org/type/Space";
@@ -288,7 +288,10 @@ var COMPOSER_SPACE_LOCK = "dxos.org/plugin/space/lock";
288
288
  var SHARED = "shared-spaces";
289
289
  var EMPTY_ARRAY = [];
290
290
  var memoizeQuery = (spaceOrEcho, filter, options) => {
291
- const key = isSpace(spaceOrEcho) ? spaceOrEcho.id : void 0;
291
+ const key = JSON.stringify({
292
+ space: isSpace(spaceOrEcho) ? spaceOrEcho.id : void 0,
293
+ filter: Filter.from(filter).toProto()
294
+ });
292
295
  const query = memoize(() => isSpace(spaceOrEcho) ? spaceOrEcho.db.query(filter, options) : spaceOrEcho?.query(filter, options), key);
293
296
  const unsubscribe = memoize(() => query?.subscribe(), key);
294
297
  cleanup(() => unsubscribe?.());
@@ -361,6 +364,11 @@ var constructSpaceNode = ({ space, navigable = false, personal, namesCache, reso
361
364
  return {
362
365
  id: space.id,
363
366
  type: SPACE_TYPE,
367
+ cacheable: [
368
+ "label",
369
+ "icon",
370
+ "role"
371
+ ],
364
372
  data: space,
365
373
  properties: {
366
374
  ...partials,
@@ -640,6 +648,11 @@ var createObjectNode = ({ object, space, navigable = false, resolve }) => {
640
648
  return {
641
649
  id: fullyQualifiedId2(object),
642
650
  type,
651
+ cacheable: [
652
+ "label",
653
+ "icon",
654
+ "role"
655
+ ],
643
656
  data: object,
644
657
  properties: {
645
658
  ...partials,
@@ -833,7 +846,7 @@ var cloneObject = async (object, resolve, newSpace) => {
833
846
  const serializer = metadata.serializer;
834
847
  invariant(serializer, `No serializer for type: ${typename}`, {
835
848
  F: __dxlog_file,
836
- L: 632,
849
+ L: 639,
837
850
  S: void 0,
838
851
  A: [
839
852
  "serializer",
@@ -1861,7 +1874,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1861
1874
  if (typeof defaultSpace.properties[COMPOSER_SPACE_LOCK] !== "boolean") {
1862
1875
  defaultSpace.properties[COMPOSER_SPACE_LOCK] = true;
1863
1876
  }
1864
- const { objects: [spacesOrder] } = await defaultSpace.db.query(Filter.schema(Expando, {
1877
+ const { objects: [spacesOrder] } = await defaultSpace.db.query(Filter2.schema(Expando, {
1865
1878
  key: SHARED
1866
1879
  })).run();
1867
1880
  if (!spacesOrder) {
@@ -1905,17 +1918,25 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1905
1918
  });
1906
1919
  }).unsubscribe);
1907
1920
  subscriptions.add(scheduledEffect(() => ({
1908
- ids: openIds(location.active),
1909
- removed: location.closed ? [
1910
- location.closed
1911
- ].flat() : []
1912
- }), ({ ids, removed }) => {
1921
+ open: openIds(location.active, layout.layoutMode === "solo" ? [
1922
+ "solo"
1923
+ ] : [
1924
+ "main"
1925
+ ]),
1926
+ closed: [
1927
+ ...location.closed
1928
+ ]
1929
+ }), ({ open, closed }) => {
1913
1930
  const send = () => {
1914
1931
  const spaces = client.spaces.get();
1915
1932
  const identity = client.halo.identity.get();
1916
1933
  if (identity && location.active) {
1917
- const idsBySpace = reduceGroupBy(ids, (id) => {
1918
- const [spaceId] = id.split(":");
1934
+ const idsBySpace = reduceGroupBy(open, (id) => {
1935
+ const [spaceId] = parseFullyQualifiedId(id);
1936
+ return spaceId;
1937
+ });
1938
+ const removedBySpace = reduceGroupBy(closed, (id) => {
1939
+ const [spaceId] = parseFullyQualifiedId(id);
1919
1940
  return spaceId;
1920
1941
  });
1921
1942
  for (const space of spaces) {
@@ -1923,7 +1944,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1923
1944
  idsBySpace.set(space.id, []);
1924
1945
  }
1925
1946
  }
1926
- for (const [spaceId, ids2] of idsBySpace) {
1947
+ for (const [spaceId, added] of idsBySpace) {
1948
+ const removed = removedBySpace.get(spaceId) ?? [];
1927
1949
  const space = spaces.find((space2) => space2.id === spaceId);
1928
1950
  if (!space) {
1929
1951
  continue;
@@ -1933,15 +1955,14 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1933
1955
  attended: attention.attended ? [
1934
1956
  ...attention.attended
1935
1957
  ] : [],
1936
- added: ids2,
1937
- // TODO(Zan): When we re-open a part, we should remove it from the removed list in the navigation plugin.
1938
- removed: removed.filter((id) => !ids2.includes(id))
1958
+ added,
1959
+ removed
1939
1960
  }).catch((err) => {
1940
1961
  log3.warn("Failed to broadcast active node for presence.", {
1941
1962
  err: err.message
1942
1963
  }, {
1943
1964
  F: __dxlog_file6,
1944
- L: 292,
1965
+ L: 300,
1945
1966
  S: void 0,
1946
1967
  C: (f, a) => f(...a)
1947
1968
  });
@@ -1959,7 +1980,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1959
1980
  spaceSubscriptions.add(space.listen("viewing", (message) => {
1960
1981
  const { added, removed, attended } = message.payload;
1961
1982
  const identityKey = PublicKey2.safeFrom(message.payload.identityKey);
1962
- if (identityKey && Array.isArray(added) && Array.isArray(removed)) {
1983
+ const currentIdentity = client.halo.identity.get();
1984
+ if (identityKey && !currentIdentity?.identityKey.equals(identityKey) && Array.isArray(added) && Array.isArray(removed)) {
1963
1985
  added.forEach((id) => {
1964
1986
  if (typeof id === "string") {
1965
1987
  if (!(id in state.values.viewersByObject)) {
@@ -2228,6 +2250,10 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2228
2250
  {
2229
2251
  id: SPACES,
2230
2252
  type: SPACES,
2253
+ cacheable: [
2254
+ "label",
2255
+ "role"
2256
+ ],
2231
2257
  properties: {
2232
2258
  label: [
2233
2259
  "spaces label",
@@ -2241,7 +2267,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2241
2267
  childrenPersistenceClass: "echo",
2242
2268
  onRearrangeChildren: async (nextOrder) => {
2243
2269
  graph._sortEdges(SPACES, "outbound", nextOrder.map(({ id }) => id));
2244
- const { objects: [spacesOrder] } = await client.spaces.default.db.query(Filter.schema(Expando, {
2270
+ const { objects: [spacesOrder] } = await client.spaces.default.db.query(Filter2.schema(Expando, {
2245
2271
  key: SHARED
2246
2272
  })).run();
2247
2273
  if (spacesOrder) {
@@ -2249,7 +2275,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2249
2275
  } else {
2250
2276
  log3.warn("spaces order object not found", void 0, {
2251
2277
  F: __dxlog_file6,
2252
- L: 596,
2278
+ L: 612,
2253
2279
  S: void 0,
2254
2280
  C: (f, a) => f(...a)
2255
2281
  });
@@ -2314,7 +2340,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2314
2340
  return;
2315
2341
  }
2316
2342
  try {
2317
- const [spacesOrder] = memoizeQuery(client.spaces.default, Filter.schema(Expando, {
2343
+ const [spacesOrder] = memoizeQuery(client.spaces.default, Filter2.schema(Expando, {
2318
2344
  key: SHARED
2319
2345
  }));
2320
2346
  const order = spacesOrder?.order ?? [];
@@ -2334,37 +2360,31 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2334
2360
  }));
2335
2361
  } catch {
2336
2362
  }
2337
- }
2338
- }),
2339
- // Find an object by its fully qualified id.
2340
- createExtension({
2341
- id: `${SPACE_PLUGIN}/objects`,
2363
+ },
2342
2364
  resolver: ({ id }) => {
2343
- const [spaceId, objectId] = id.split(":");
2344
- const space = client.spaces.get().find((space2) => space2.id === spaceId);
2345
- if (!space) {
2365
+ if (id.length !== SPACE_ID_LENGTH) {
2346
2366
  return;
2347
2367
  }
2348
- const spaceState = toSignal((onChange) => space.state.subscribe(() => onChange()).unsubscribe, () => space.state.get(), space.id);
2349
- if (spaceState !== SpaceState2.SPACE_READY) {
2368
+ const spaces = toSignal((onChange) => client.spaces.subscribe(() => onChange()).unsubscribe, () => client.spaces.get());
2369
+ const isReady = toSignal((onChange) => client.spaces.isReady.subscribe(() => onChange()).unsubscribe, () => client.spaces.isReady.get());
2370
+ if (!spaces || !isReady) {
2350
2371
  return;
2351
2372
  }
2352
- const store = memoize2(() => signal(space.db.getObjectById(objectId)), id);
2353
- memoize2(() => {
2354
- if (!store.value) {
2355
- void space.db.loadObjectById(objectId).then((o) => store.value = o);
2356
- }
2357
- }, id);
2358
- const object = store.value;
2359
- if (!object) {
2373
+ const space = spaces.find((space2) => space2.id === id);
2374
+ if (!space) {
2360
2375
  return;
2361
2376
  }
2362
- return createObjectNode({
2363
- object,
2364
- space,
2365
- resolve,
2366
- navigable: state.values.navigableCollections
2367
- });
2377
+ if (space.state.get() === SpaceState2.SPACE_INACTIVE) {
2378
+ return false;
2379
+ } else {
2380
+ return constructSpaceNode({
2381
+ space,
2382
+ navigable: state.values.navigableCollections,
2383
+ personal: space === client.spaces.default,
2384
+ namesCache: state.values.spaceNames,
2385
+ resolve
2386
+ });
2387
+ }
2368
2388
  }
2369
2389
  }),
2370
2390
  // Create space actions and action groups.
@@ -2408,23 +2428,9 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2408
2428
  })).filter(nonNullable);
2409
2429
  }
2410
2430
  }),
2411
- // Create collection actions and action groups.
2412
- createExtension({
2413
- id: `${SPACE_PLUGIN}/object-actions`,
2414
- filter: (node) => isEchoObject2(node.data),
2415
- actionGroups: ({ node }) => constructObjectActionGroups({
2416
- object: node.data,
2417
- dispatch,
2418
- navigable: state.values.navigableCollections
2419
- }),
2420
- actions: ({ node }) => constructObjectActions({
2421
- node,
2422
- dispatch
2423
- })
2424
- }),
2425
- // Create nodes for objects in collections.
2431
+ // Create nodes for objects in a collection or by its fully qualified id.
2426
2432
  createExtension({
2427
- id: `${SPACE_PLUGIN}/collection-objects`,
2433
+ id: `${SPACE_PLUGIN}/objects`,
2428
2434
  filter: (node) => node.data instanceof CollectionType,
2429
2435
  connector: ({ node }) => {
2430
2436
  const collection = node.data;
@@ -2438,8 +2444,68 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2438
2444
  resolve,
2439
2445
  navigable: state.values.navigableCollections
2440
2446
  })).filter(nonNullable);
2447
+ },
2448
+ resolver: ({ id }) => {
2449
+ if (id.length !== FQ_ID_LENGTH) {
2450
+ return;
2451
+ }
2452
+ const [spaceId, objectId] = id.split(":");
2453
+ if (spaceId.length !== SPACE_ID_LENGTH && objectId.length !== OBJECT_ID_LENGTH) {
2454
+ return;
2455
+ }
2456
+ const space = client.spaces.get().find((space2) => space2.id === spaceId);
2457
+ if (!space) {
2458
+ return;
2459
+ }
2460
+ const spaceState = toSignal((onChange) => space.state.subscribe(() => onChange()).unsubscribe, () => space.state.get(), space.id);
2461
+ if (spaceState !== SpaceState2.SPACE_READY) {
2462
+ return;
2463
+ }
2464
+ const store = memoize2(() => signal(space.db.getObjectById(objectId)), id);
2465
+ memoize2(() => {
2466
+ if (!store.value) {
2467
+ void space.db.query({
2468
+ id: objectId
2469
+ }).first().then((o) => store.value = o).catch((err) => log3.catch(err, {
2470
+ objectId
2471
+ }, {
2472
+ F: __dxlog_file6,
2473
+ L: 835,
2474
+ S: void 0,
2475
+ C: (f, a) => f(...a)
2476
+ }));
2477
+ }
2478
+ }, id);
2479
+ const object = store.value;
2480
+ if (!object) {
2481
+ return;
2482
+ }
2483
+ if (isDeleted(object)) {
2484
+ return false;
2485
+ } else {
2486
+ return createObjectNode({
2487
+ object,
2488
+ space,
2489
+ resolve,
2490
+ navigable: state.values.navigableCollections
2491
+ });
2492
+ }
2441
2493
  }
2442
2494
  }),
2495
+ // Create collection actions and action groups.
2496
+ createExtension({
2497
+ id: `${SPACE_PLUGIN}/object-actions`,
2498
+ filter: (node) => isEchoObject2(node.data),
2499
+ actionGroups: ({ node }) => constructObjectActionGroups({
2500
+ object: node.data,
2501
+ dispatch,
2502
+ navigable: state.values.navigableCollections
2503
+ }),
2504
+ actions: ({ node }) => constructObjectActions({
2505
+ node,
2506
+ dispatch
2507
+ })
2508
+ }),
2443
2509
  // Create nodes for object settings.
2444
2510
  createExtension({
2445
2511
  id: `${SPACE_PLUGIN}/settings-for-subject`,
@@ -2451,7 +2517,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2451
2517
  const icon = "ph--gear--regular";
2452
2518
  const [subjectId] = id.split("~");
2453
2519
  const { spaceId, objectId } = parseId(subjectId);
2454
- const space = client.spaces.get().find((space2) => space2.id === spaceId);
2520
+ const spaces = toSignal((onChange) => client.spaces.subscribe(() => onChange()).unsubscribe, () => client.spaces.get());
2521
+ const space = spaces?.find((space2) => space2.id === spaceId && space2.state.get() === SpaceState2.SPACE_READY);
2455
2522
  if (!objectId) {
2456
2523
  const label2 = space ? space.properties.name || [
2457
2524
  "unnamed space label",
@@ -2477,13 +2544,9 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2477
2544
  }
2478
2545
  };
2479
2546
  }
2480
- const object = toSignal((onChange) => {
2481
- const timeout = setTimeout(async () => {
2482
- await space?.db.loadObjectById(objectId);
2483
- onChange();
2484
- });
2485
- return () => clearTimeout(timeout);
2486
- }, () => space?.db.getObjectById(objectId), subjectId);
2547
+ const [object] = memoizeQuery(space, {
2548
+ id: objectId
2549
+ });
2487
2550
  if (!object || !subjectId) {
2488
2551
  return;
2489
2552
  }
@@ -2946,7 +3009,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2946
3009
  const objects = intent.data?.objects ?? intent.data?.result;
2947
3010
  invariant2(Array.isArray(objects), void 0, {
2948
3011
  F: __dxlog_file6,
2949
- L: 1291,
3012
+ L: 1349,
2950
3013
  S: void 0,
2951
3014
  A: [
2952
3015
  "Array.isArray(objects)",