@dxos/plugin-space 0.6.11 → 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,33 +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;
1732
1817
  // TODO(burdon): Add role name syntax to minimal plugin docs.
1733
1818
  case "tree--empty":
1734
1819
  switch (true) {
1735
1820
  case data.plugin === SPACE_PLUGIN:
1736
- return /* @__PURE__ */ React17.createElement(EmptyTree, null);
1821
+ return /* @__PURE__ */ React18.createElement(EmptyTree, null);
1737
1822
  case (isGraphNode(data.activeNode) && isSpace2(data.activeNode.data)):
1738
- return /* @__PURE__ */ React17.createElement(EmptySpace, null);
1823
+ return /* @__PURE__ */ React18.createElement(EmptySpace, null);
1739
1824
  default:
1740
1825
  return null;
1741
1826
  }
1742
1827
  case "dialog":
1743
1828
  if (data.component === "dxos.org/plugin/space/InvitationManagerDialog") {
1744
- 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, {
1745
1830
  active: true,
1746
1831
  ...data.subject
1747
1832
  })));
@@ -1750,20 +1835,20 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1750
1835
  }
1751
1836
  case "popover":
1752
1837
  if (data.component === "dxos.org/plugin/space/RenameSpacePopover" && isSpace2(data.subject)) {
1753
- return /* @__PURE__ */ React17.createElement(PopoverRenameSpace, {
1838
+ return /* @__PURE__ */ React18.createElement(PopoverRenameSpace, {
1754
1839
  space: data.subject
1755
1840
  });
1756
1841
  }
1757
1842
  if (data.component === "dxos.org/plugin/space/RenameObjectPopover" && isReactiveObject2(data.subject)) {
1758
- return /* @__PURE__ */ React17.createElement(PopoverRenameObject, {
1843
+ return /* @__PURE__ */ React18.createElement(PopoverRenameObject, {
1759
1844
  object: data.subject
1760
1845
  });
1761
1846
  }
1762
1847
  return null;
1763
1848
  case "presence--glyph": {
1764
- return isReactiveObject2(data.object) ? /* @__PURE__ */ React17.createElement(SmallPresenceLive, {
1849
+ return isReactiveObject2(data.object) ? /* @__PURE__ */ React18.createElement(SmallPresenceLive, {
1765
1850
  viewers: state.values.viewersByObject[fullyQualifiedId4(data.object)]
1766
- }) : /* @__PURE__ */ React17.createElement(SmallPresence, {
1851
+ }) : /* @__PURE__ */ React18.createElement(SmallPresence, {
1767
1852
  count: 0
1768
1853
  });
1769
1854
  }
@@ -1777,30 +1862,33 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1777
1862
  const space = isSpace2(data.object) ? data.object : getSpace4(data.object);
1778
1863
  const object = isSpace2(data.object) ? data.object.state.get() === SpaceState3.SPACE_READY ? space?.properties[CollectionType.typename] : void 0 : data.object;
1779
1864
  return space && object ? {
1780
- node: /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(SpacePresence, {
1865
+ node: /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SpacePresence, {
1781
1866
  object
1782
- }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React17.createElement(ShareSpaceButton, {
1867
+ }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React18.createElement(ShareSpaceButton, {
1783
1868
  spaceId: space.id
1784
1869
  })),
1785
1870
  disposition: "hoist"
1786
1871
  } : null;
1787
1872
  }
1788
1873
  case "section":
1789
- return data.object instanceof CollectionType ? /* @__PURE__ */ React17.createElement(CollectionSection, {
1874
+ return data.object instanceof CollectionType ? /* @__PURE__ */ React18.createElement(CollectionSection, {
1790
1875
  collection: data.object
1791
1876
  }) : null;
1792
1877
  case "settings":
1793
- return data.plugin === meta_default.id ? /* @__PURE__ */ React17.createElement(SpaceSettings, {
1878
+ return data.plugin === meta_default.id ? /* @__PURE__ */ React18.createElement(SpaceSettings, {
1794
1879
  settings: settings.values
1795
1880
  }) : null;
1796
1881
  case "menu-footer":
1797
1882
  if (!isEchoObject2(data.object)) {
1798
1883
  return null;
1799
1884
  } else {
1800
- return /* @__PURE__ */ React17.createElement(MenuFooter, {
1885
+ return /* @__PURE__ */ React18.createElement(MenuFooter, {
1801
1886
  object: data.object
1802
1887
  });
1803
1888
  }
1889
+ case "status": {
1890
+ return /* @__PURE__ */ React18.createElement(SaveStatus, null);
1891
+ }
1804
1892
  default:
1805
1893
  return null;
1806
1894
  }
@@ -1860,8 +1948,8 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1860
1948
  spacesOrder.order = nextOrder.map(({ id }) => id);
1861
1949
  } else {
1862
1950
  log2.warn("spaces order object not found", void 0, {
1863
- F: __dxlog_file3,
1864
- L: 514,
1951
+ F: __dxlog_file4,
1952
+ L: 518,
1865
1953
  S: void 0,
1866
1954
  C: (f, a) => f(...a)
1867
1955
  });
@@ -1897,7 +1985,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1897
1985
  ns: SPACE_PLUGIN
1898
1986
  }
1899
1987
  ],
1900
- icon: (props) => /* @__PURE__ */ React17.createElement(Plus2, props),
1988
+ icon: (props) => /* @__PURE__ */ React18.createElement(Plus2, props),
1901
1989
  iconSymbol: "ph--plus--regular",
1902
1990
  disposition: "toolbar",
1903
1991
  testId: "spacePlugin.createSpace"
@@ -1923,7 +2011,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
1923
2011
  ns: SPACE_PLUGIN
1924
2012
  }
1925
2013
  ],
1926
- icon: (props) => /* @__PURE__ */ React17.createElement(SignIn, props),
2014
+ icon: (props) => /* @__PURE__ */ React18.createElement(SignIn, props),
1927
2015
  iconSymbol: "ph--sign-in--regular",
1928
2016
  testId: "spacePlugin.joinSpace"
1929
2017
  }
@@ -2379,7 +2467,7 @@ var SpacePlugin = ({ firstRun, onFirstRun } = {}) => {
2379
2467
  title: translations_default[0]["en-US"][SPACE_PLUGIN]["space limit label"],
2380
2468
  description: translations_default[0]["en-US"][SPACE_PLUGIN]["space limit description"],
2381
2469
  duration: 5e3,
2382
- icon: (props) => /* @__PURE__ */ React17.createElement(Warning2, props),
2470
+ icon: (props) => /* @__PURE__ */ React18.createElement(Warning2, props),
2383
2471
  iconSymbol: "ph--warning--regular",
2384
2472
  actionLabel: translations_default[0]["en-US"][SPACE_PLUGIN]["remove deleted objects label"],
2385
2473
  actionAlt: translations_default[0]["en-US"][SPACE_PLUGIN]["remove deleted objects alt"],
@@ -2611,6 +2699,7 @@ export {
2611
2699
  SPACE_PLUGIN,
2612
2700
  SPACE_PLUGIN_SHORT_ID,
2613
2701
  SPACE_TYPE,
2702
+ SaveStatus,
2614
2703
  ShareSpaceButton,
2615
2704
  ShareSpaceButtonImpl,
2616
2705
  SmallPresence,