@dxos/plugin-space 0.6.11-staging.e6894a4 → 0.6.12-main.5cc132e

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.
@@ -16,10 +16,10 @@ import {
16
16
  } from "./chunk-DTVUOG2C.mjs";
17
17
 
18
18
  // packages/plugins/plugin-space/src/SpacePlugin.tsx
19
- import { Plus as Plus2, SignIn, CardsThree as CardsThree2, Warning as Warning2 } from "@phosphor-icons/react";
19
+ import { CardsThree as CardsThree2, Plus as Plus2, SignIn, Warning as Warning2 } from "@phosphor-icons/react";
20
20
  import { effect, signal } from "@preact/signals-core";
21
- import React17 from "react";
22
- import { LayoutAction as LayoutAction2, Surface as Surface2, NavigationAction as NavigationAction3, openIds, firstIdInPart, parseIntentPlugin as parseIntentPlugin3, parseNavigationPlugin as parseNavigationPlugin2, parseMetadataResolverPlugin, resolvePlugin, parseGraphPlugin } from "@dxos/app-framework";
21
+ import React18 from "react";
22
+ import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction3, Surface as Surface2, firstIdInPart, openIds, parseGraphPlugin, parseIntentPlugin as parseIntentPlugin3, parseMetadataResolverPlugin, parseNavigationPlugin as parseNavigationPlugin2, resolvePlugin } from "@dxos/app-framework";
23
23
  import { EventSubscriptions } from "@dxos/async";
24
24
  import { isReactiveObject as isReactiveObject2 } from "@dxos/echo-schema";
25
25
  import { LocalStorageStore } from "@dxos/local-storage";
@@ -30,9 +30,9 @@ import { parseClientPlugin } from "@dxos/plugin-client";
30
30
  import { createExtension, isGraphNode, memoize as memoize2, toSignal } from "@dxos/plugin-graph";
31
31
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
32
32
  import { PublicKey as PublicKey2 } from "@dxos/react-client";
33
- import { create as create2, Expando, Filter, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace4, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace2, loadObjectReferences, SpaceState as SpaceState3 } from "@dxos/react-client/echo";
33
+ import { Expando, Filter, SpaceState as SpaceState3, create as create2, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace4, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace2, loadObjectReferences } from "@dxos/react-client/echo";
34
34
  import { Dialog } from "@dxos/react-ui";
35
- import { InvitationManager, osTranslations, ClipboardProvider as ClipboardProvider2 } from "@dxos/shell/react";
35
+ import { ClipboardProvider as ClipboardProvider2, InvitationManager, osTranslations } from "@dxos/shell/react";
36
36
  import { ComplexMap as ComplexMap2, nonNullable, reduceGroupBy } from "@dxos/util";
37
37
 
38
38
  // packages/plugins/plugin-space/src/components/AwaitingObject.tsx
@@ -1399,6 +1399,91 @@ var SpaceSettings = ({ settings }) => {
1399
1399
  })));
1400
1400
  };
1401
1401
 
1402
+ // packages/plugins/plugin-space/src/components/SaveStatus.tsx
1403
+ import { ArrowsClockwise, CheckCircle as CheckCircle3 } from "@phosphor-icons/react";
1404
+ import React17, { useEffect as useEffect5 } from "react";
1405
+ import { Context } from "@dxos/context";
1406
+ import { StatusBar } from "@dxos/plugin-status-bar";
1407
+ import { useClient as useClient4 } from "@dxos/react-client";
1408
+ import { useTranslation as useTranslation16 } from "@dxos/react-ui";
1409
+ import { getSize as getSize5 } from "@dxos/react-ui-theme";
1410
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SaveStatus.tsx";
1411
+ var SaveStatus = () => {
1412
+ const { t } = useTranslation16(SPACE_PLUGIN);
1413
+ const client = useClient4();
1414
+ const [state, setState] = React17.useState("saved");
1415
+ useEffect5(() => {
1416
+ return createClientSaveTracker(client, (state2) => {
1417
+ setState(state2);
1418
+ });
1419
+ }, []);
1420
+ return /* @__PURE__ */ React17.createElement(StatusBar.Item, {
1421
+ title: state === "saving" ? t("saving label") : t("saved label")
1422
+ }, state === "saving" ? /* @__PURE__ */ React17.createElement(ArrowsClockwise, {
1423
+ className: getSize5(3)
1424
+ }) : /* @__PURE__ */ React17.createElement(CheckCircle3, {
1425
+ className: getSize5(3)
1426
+ }));
1427
+ };
1428
+ var createClientSaveTracker = (client, cb) => {
1429
+ const unsubscribeCallbacks = {};
1430
+ const state = {};
1431
+ const install = (spaces) => {
1432
+ for (const space of spaces) {
1433
+ if (state[space.id]) {
1434
+ continue;
1435
+ }
1436
+ state[space.id] = "saved";
1437
+ unsubscribeCallbacks[space.id] = createSpaceSaveTracker(space, (s) => {
1438
+ state[space.id] = s;
1439
+ cb(Object.values(state).some((s2) => s2 === "saving") ? "saving" : "saved");
1440
+ });
1441
+ }
1442
+ };
1443
+ client.spaces.subscribe((spaces) => {
1444
+ install(spaces);
1445
+ });
1446
+ install(client.spaces.get());
1447
+ return () => {
1448
+ for (const unsubscribe of Object.values(unsubscribeCallbacks)) {
1449
+ unsubscribe();
1450
+ }
1451
+ };
1452
+ };
1453
+ var createSpaceSaveTracker = (space, cb) => {
1454
+ const ctx = new Context(void 0, {
1455
+ F: __dxlog_file3,
1456
+ L: 67
1457
+ });
1458
+ void space.waitUntilReady().then(() => {
1459
+ if (ctx.disposed) {
1460
+ return;
1461
+ }
1462
+ let hasUnsavedChanges = false;
1463
+ let lastFlushPromise;
1464
+ space.crud.saveStateChanged.on(ctx, ({ unsavedDocuments }) => {
1465
+ hasUnsavedChanges = unsavedDocuments.length > 0;
1466
+ });
1467
+ space.crud.saveStateChanged.debounce(500).on(ctx, () => {
1468
+ if (hasUnsavedChanges) {
1469
+ lastFlushPromise = void 0;
1470
+ cb("saving");
1471
+ } else {
1472
+ const flushPromise = space.crud.flush();
1473
+ lastFlushPromise = flushPromise;
1474
+ void flushPromise.then(() => {
1475
+ if (lastFlushPromise === flushPromise) {
1476
+ cb("saved");
1477
+ }
1478
+ });
1479
+ }
1480
+ });
1481
+ });
1482
+ return () => {
1483
+ void ctx.dispose();
1484
+ };
1485
+ };
1486
+
1402
1487
  // packages/plugins/plugin-space/src/translations.ts
1403
1488
  var translations_default = [
1404
1489
  {
@@ -1485,7 +1570,7 @@ var translations_default = [
1485
1570
  ];
1486
1571
 
1487
1572
  // packages/plugins/plugin-space/src/SpacePlugin.tsx
1488
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/SpacePlugin.tsx";
1573
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/SpacePlugin.tsx";
1489
1574
  var ACTIVE_NODE_BROADCAST_INTERVAL = 3e4;
1490
1575
  var OBJECT_ID_LENGTH = 60;
1491
1576
  var SPACE_MAX_OBJECTS = 500;
@@ -1572,8 +1657,8 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1572
1657
  log2.warn("Failed to broadcast active node for presence.", {
1573
1658
  err: err.message
1574
1659
  }, {
1575
- F: __dxlog_file3,
1576
- L: 222,
1660
+ F: __dxlog_file4,
1661
+ L: 223,
1577
1662
  S: void 0,
1578
1663
  C: (f, a) => f(...a)
1579
1664
  });
@@ -1682,7 +1767,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1682
1767
  ...translations_default,
1683
1768
  osTranslations
1684
1769
  ],
1685
- root: () => state.values.awaiting ? /* @__PURE__ */ React17.createElement(AwaitingObject, {
1770
+ root: () => state.values.awaiting ? /* @__PURE__ */ React18.createElement(AwaitingObject, {
1686
1771
  id: state.values.awaiting
1687
1772
  }) : null,
1688
1773
  metadata: {
@@ -1694,7 +1779,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1694
1779
  ns: SPACE_PLUGIN
1695
1780
  }
1696
1781
  ],
1697
- icon: (props) => /* @__PURE__ */ React17.createElement(CardsThree2, props),
1782
+ icon: (props) => /* @__PURE__ */ React18.createElement(CardsThree2, props),
1698
1783
  iconSymbol: "ph--cards-three--regular",
1699
1784
  // TODO(wittjosiah): Move out of metadata.
1700
1785
  loadReferences: (collection) => loadObjectReferences(collection, (collection2) => [
@@ -1715,32 +1800,33 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1715
1800
  switch (role) {
1716
1801
  case "article":
1717
1802
  case "main":
1718
- return isSpace2(primary) && primary.state.get() === SpaceState3.SPACE_READY ? /* @__PURE__ */ React17.createElement(Surface2, {
1803
+ return isSpace2(primary) && primary.state.get() === SpaceState3.SPACE_READY ? /* @__PURE__ */ React18.createElement(Surface2, {
1719
1804
  data: {
1720
1805
  active: primary.properties[CollectionType.typename]
1721
1806
  },
1722
1807
  role,
1723
1808
  ...rest
1724
1809
  }) : primary instanceof CollectionType ? {
1725
- node: /* @__PURE__ */ React17.createElement(CollectionMain, {
1810
+ node: /* @__PURE__ */ React18.createElement(CollectionMain, {
1726
1811
  collection: primary
1727
1812
  }),
1728
1813
  disposition: "fallback"
1729
- } : typeof primary === "string" && primary.length === OBJECT_ID_LENGTH ? /* @__PURE__ */ React17.createElement(MissingObject, {
1814
+ } : typeof primary === "string" && primary.length === OBJECT_ID_LENGTH ? /* @__PURE__ */ React18.createElement(MissingObject, {
1730
1815
  id: primary
1731
1816
  }) : null;
1817
+ // TODO(burdon): Add role name syntax to minimal plugin docs.
1732
1818
  case "tree--empty":
1733
1819
  switch (true) {
1734
1820
  case data.plugin === SPACE_PLUGIN:
1735
- return /* @__PURE__ */ React17.createElement(EmptyTree, null);
1821
+ return /* @__PURE__ */ React18.createElement(EmptyTree, null);
1736
1822
  case (isGraphNode(data.activeNode) && isSpace2(data.activeNode.data)):
1737
- return /* @__PURE__ */ React17.createElement(EmptySpace, null);
1823
+ return /* @__PURE__ */ React18.createElement(EmptySpace, null);
1738
1824
  default:
1739
1825
  return null;
1740
1826
  }
1741
1827
  case "dialog":
1742
1828
  if (data.component === "dxos.org/plugin/space/InvitationManagerDialog") {
1743
- return /* @__PURE__ */ React17.createElement(Dialog.Content, null, /* @__PURE__ */ React17.createElement(ClipboardProvider2, null, /* @__PURE__ */ React17.createElement(InvitationManager, {
1829
+ return /* @__PURE__ */ React18.createElement(Dialog.Content, null, /* @__PURE__ */ React18.createElement(ClipboardProvider2, null, /* @__PURE__ */ React18.createElement(InvitationManager, {
1744
1830
  active: true,
1745
1831
  ...data.subject
1746
1832
  })));
@@ -1749,20 +1835,20 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1749
1835
  }
1750
1836
  case "popover":
1751
1837
  if (data.component === "dxos.org/plugin/space/RenameSpacePopover" && isSpace2(data.subject)) {
1752
- return /* @__PURE__ */ React17.createElement(PopoverRenameSpace, {
1838
+ return /* @__PURE__ */ React18.createElement(PopoverRenameSpace, {
1753
1839
  space: data.subject
1754
1840
  });
1755
1841
  }
1756
1842
  if (data.component === "dxos.org/plugin/space/RenameObjectPopover" && isReactiveObject2(data.subject)) {
1757
- return /* @__PURE__ */ React17.createElement(PopoverRenameObject, {
1843
+ return /* @__PURE__ */ React18.createElement(PopoverRenameObject, {
1758
1844
  object: data.subject
1759
1845
  });
1760
1846
  }
1761
1847
  return null;
1762
1848
  case "presence--glyph": {
1763
- return isReactiveObject2(data.object) ? /* @__PURE__ */ React17.createElement(SmallPresenceLive, {
1849
+ return isReactiveObject2(data.object) ? /* @__PURE__ */ React18.createElement(SmallPresenceLive, {
1764
1850
  viewers: state.values.viewersByObject[fullyQualifiedId4(data.object)]
1765
- }) : /* @__PURE__ */ React17.createElement(SmallPresence, {
1851
+ }) : /* @__PURE__ */ React18.createElement(SmallPresence, {
1766
1852
  count: 0
1767
1853
  });
1768
1854
  }
@@ -1776,30 +1862,33 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1776
1862
  const space = isSpace2(data.object) ? data.object : getSpace4(data.object);
1777
1863
  const object = isSpace2(data.object) ? data.object.state.get() === SpaceState3.SPACE_READY ? space?.properties[CollectionType.typename] : void 0 : data.object;
1778
1864
  return space && object ? {
1779
- node: /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(SpacePresence, {
1865
+ node: /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SpacePresence, {
1780
1866
  object
1781
- }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React17.createElement(ShareSpaceButton, {
1867
+ }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React18.createElement(ShareSpaceButton, {
1782
1868
  spaceId: space.id
1783
1869
  })),
1784
1870
  disposition: "hoist"
1785
1871
  } : null;
1786
1872
  }
1787
1873
  case "section":
1788
- return data.object instanceof CollectionType ? /* @__PURE__ */ React17.createElement(CollectionSection, {
1874
+ return data.object instanceof CollectionType ? /* @__PURE__ */ React18.createElement(CollectionSection, {
1789
1875
  collection: data.object
1790
1876
  }) : null;
1791
1877
  case "settings":
1792
- return data.plugin === meta_default.id ? /* @__PURE__ */ React17.createElement(SpaceSettings, {
1878
+ return data.plugin === meta_default.id ? /* @__PURE__ */ React18.createElement(SpaceSettings, {
1793
1879
  settings: settings.values
1794
1880
  }) : null;
1795
1881
  case "menu-footer":
1796
1882
  if (!isEchoObject2(data.object)) {
1797
1883
  return null;
1798
1884
  } else {
1799
- return /* @__PURE__ */ React17.createElement(MenuFooter, {
1885
+ return /* @__PURE__ */ React18.createElement(MenuFooter, {
1800
1886
  object: data.object
1801
1887
  });
1802
1888
  }
1889
+ case "status": {
1890
+ return /* @__PURE__ */ React18.createElement(SaveStatus, null);
1891
+ }
1803
1892
  default:
1804
1893
  return null;
1805
1894
  }
@@ -1859,8 +1948,8 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1859
1948
  spacesOrder.order = nextOrder.map(({ id }) => id);
1860
1949
  } else {
1861
1950
  log2.warn("spaces order object not found", void 0, {
1862
- F: __dxlog_file3,
1863
- L: 514,
1951
+ F: __dxlog_file4,
1952
+ L: 518,
1864
1953
  S: void 0,
1865
1954
  C: (f, a) => f(...a)
1866
1955
  });
@@ -1896,7 +1985,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1896
1985
  ns: SPACE_PLUGIN
1897
1986
  }
1898
1987
  ],
1899
- icon: (props) => /* @__PURE__ */ React17.createElement(Plus2, props),
1988
+ icon: (props) => /* @__PURE__ */ React18.createElement(Plus2, props),
1900
1989
  iconSymbol: "ph--plus--regular",
1901
1990
  disposition: "toolbar",
1902
1991
  testId: "spacePlugin.createSpace"
@@ -1922,7 +2011,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1922
2011
  ns: SPACE_PLUGIN
1923
2012
  }
1924
2013
  ],
1925
- icon: (props) => /* @__PURE__ */ React17.createElement(SignIn, props),
2014
+ icon: (props) => /* @__PURE__ */ React18.createElement(SignIn, props),
1926
2015
  iconSymbol: "ph--sign-in--regular",
1927
2016
  testId: "spacePlugin.joinSpace"
1928
2017
  }
@@ -1930,7 +2019,8 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1930
2019
  ],
1931
2020
  connector: () => {
1932
2021
  const spaces = toSignal((onChange) => client.spaces.subscribe(() => onChange()).unsubscribe, () => client.spaces.get());
1933
- if (!spaces) {
2022
+ const isReady = toSignal((onChange) => client.spaces.isReady.subscribe(() => onChange()).unsubscribe, () => client.spaces.isReady.get());
2023
+ if (!spaces || !isReady) {
1934
2024
  return;
1935
2025
  }
1936
2026
  const [spacesOrder] = memoizeQuery(client.spaces.default, Filter.schema(Expando, {
@@ -2377,7 +2467,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
2377
2467
  title: translations_default[0]["en-US"][SPACE_PLUGIN]["space limit label"],
2378
2468
  description: translations_default[0]["en-US"][SPACE_PLUGIN]["space limit description"],
2379
2469
  duration: 5e3,
2380
- icon: (props) => /* @__PURE__ */ React17.createElement(Warning2, props),
2470
+ icon: (props) => /* @__PURE__ */ React18.createElement(Warning2, props),
2381
2471
  iconSymbol: "ph--warning--regular",
2382
2472
  actionLabel: translations_default[0]["en-US"][SPACE_PLUGIN]["remove deleted objects label"],
2383
2473
  actionAlt: translations_default[0]["en-US"][SPACE_PLUGIN]["remove deleted objects alt"],
@@ -2609,6 +2699,7 @@ export {
2609
2699
  SPACE_PLUGIN,
2610
2700
  SPACE_PLUGIN_SHORT_ID,
2611
2701
  SPACE_TYPE,
2702
+ SaveStatus,
2612
2703
  ShareSpaceButton,
2613
2704
  ShareSpaceButtonImpl,
2614
2705
  SmallPresence,