@dxos/plugin-space 0.7.4 → 0.7.5-feature-compute.4d9d99a
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/dist/lib/browser/app-graph-builder-5D2QB43K.mjs +365 -0
- package/dist/lib/browser/app-graph-builder-5D2QB43K.mjs.map +7 -0
- package/dist/lib/browser/app-graph-serializer-VNWPLPDF.mjs +80 -0
- package/dist/lib/browser/app-graph-serializer-VNWPLPDF.mjs.map +7 -0
- package/dist/lib/browser/chunk-5TBRONF6.mjs +133 -0
- package/dist/lib/browser/chunk-5TBRONF6.mjs.map +7 -0
- package/dist/lib/browser/chunk-6SWQRWOD.mjs +1672 -0
- package/dist/lib/browser/chunk-6SWQRWOD.mjs.map +7 -0
- package/dist/lib/browser/chunk-HCXWKGTE.mjs +316 -0
- package/dist/lib/browser/chunk-HCXWKGTE.mjs.map +7 -0
- package/dist/lib/browser/chunk-SOXNANA6.mjs +12 -0
- package/dist/lib/browser/chunk-SOXNANA6.mjs.map +7 -0
- package/dist/lib/browser/chunk-UH5P4UL3.mjs +21 -0
- package/dist/lib/browser/chunk-UH5P4UL3.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZBKFJNHH.mjs +523 -0
- package/dist/lib/browser/chunk-ZBKFJNHH.mjs.map +7 -0
- package/dist/lib/browser/identity-created-EC5FOCX2.mjs +28 -0
- package/dist/lib/browser/identity-created-EC5FOCX2.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +192 -3521
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-VBL572N7.mjs +459 -0
- package/dist/lib/browser/intent-resolver-VBL572N7.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-root-AZJFNTKK.mjs +28 -0
- package/dist/lib/browser/react-root-AZJFNTKK.mjs.map +7 -0
- package/dist/lib/browser/react-surface-E2VSYVNZ.mjs +238 -0
- package/dist/lib/browser/react-surface-E2VSYVNZ.mjs.map +7 -0
- package/dist/lib/browser/settings-ASFF5BZL.mjs +24 -0
- package/dist/lib/browser/settings-ASFF5BZL.mjs.map +7 -0
- package/dist/lib/browser/spaces-ready-4SFNS5JQ.mjs +200 -0
- package/dist/lib/browser/spaces-ready-4SFNS5JQ.mjs.map +7 -0
- package/dist/lib/browser/state-MS4KYJWI.mjs +47 -0
- package/dist/lib/browser/state-MS4KYJWI.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +14 -5
- package/dist/lib/node/app-graph-builder-ZQ5S62YR.cjs +368 -0
- package/dist/lib/node/app-graph-builder-ZQ5S62YR.cjs.map +7 -0
- package/dist/lib/node/app-graph-serializer-72S7P33H.cjs +88 -0
- package/dist/lib/node/app-graph-serializer-72S7P33H.cjs.map +7 -0
- package/dist/lib/node/chunk-56NGXG2A.cjs +41 -0
- package/dist/lib/node/chunk-56NGXG2A.cjs.map +7 -0
- package/dist/lib/node/{meta.cjs → chunk-AO4EW2RX.cjs} +12 -13
- package/dist/lib/node/chunk-AO4EW2RX.cjs.map +7 -0
- package/dist/lib/node/chunk-BQRNTKSQ.cjs +150 -0
- package/dist/lib/node/chunk-BQRNTKSQ.cjs.map +7 -0
- package/dist/lib/node/chunk-DDZYVNVP.cjs +345 -0
- package/dist/lib/node/chunk-DDZYVNVP.cjs.map +7 -0
- package/dist/lib/node/chunk-M64YG2FY.cjs +1669 -0
- package/dist/lib/node/chunk-M64YG2FY.cjs.map +7 -0
- package/dist/lib/node/chunk-Z34MTEU7.cjs +551 -0
- package/dist/lib/node/chunk-Z34MTEU7.cjs.map +7 -0
- package/dist/lib/node/identity-created-IMDS4A6A.cjs +44 -0
- package/dist/lib/node/identity-created-IMDS4A6A.cjs.map +7 -0
- package/dist/lib/node/index.cjs +175 -3506
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/intent-resolver-S4HZABYI.cjs +458 -0
- package/dist/lib/node/intent-resolver-S4HZABYI.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/react-root-RB3OM3QG.cjs +50 -0
- package/dist/lib/node/react-root-RB3OM3QG.cjs.map +7 -0
- package/dist/lib/node/react-surface-TLKQEHHT.cjs +233 -0
- package/dist/lib/node/react-surface-TLKQEHHT.cjs.map +7 -0
- package/dist/lib/node/settings-QLCKAUHK.cjs +38 -0
- package/dist/lib/node/settings-QLCKAUHK.cjs.map +7 -0
- package/dist/lib/node/spaces-ready-RZTKEXOL.cjs +211 -0
- package/dist/lib/node/spaces-ready-RZTKEXOL.cjs.map +7 -0
- package/dist/lib/node/state-4UIOUKLJ.cjs +61 -0
- package/dist/lib/node/state-4UIOUKLJ.cjs.map +7 -0
- package/dist/lib/node/types/index.cjs +23 -14
- package/dist/lib/node/types/index.cjs.map +2 -2
- package/dist/lib/node-esm/app-graph-builder-CD6IYPSS.mjs +366 -0
- package/dist/lib/node-esm/app-graph-builder-CD6IYPSS.mjs.map +7 -0
- package/dist/lib/node-esm/app-graph-serializer-CFXS6ZE2.mjs +81 -0
- package/dist/lib/node-esm/app-graph-serializer-CFXS6ZE2.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-375RB3CZ.mjs +22 -0
- package/dist/lib/node-esm/chunk-375RB3CZ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-7FUVU45N.mjs +14 -0
- package/dist/lib/node-esm/chunk-7FUVU45N.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CLGCKZ2D.mjs +317 -0
- package/dist/lib/node-esm/chunk-CLGCKZ2D.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CMKML5IN.mjs +1673 -0
- package/dist/lib/node-esm/chunk-CMKML5IN.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-FUMGYUD3.mjs +524 -0
- package/dist/lib/node-esm/chunk-FUMGYUD3.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-M4XTHK35.mjs +134 -0
- package/dist/lib/node-esm/chunk-M4XTHK35.mjs.map +7 -0
- package/dist/lib/node-esm/identity-created-SJYZZ7Q3.mjs +29 -0
- package/dist/lib/node-esm/identity-created-SJYZZ7Q3.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +192 -3521
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/intent-resolver-OIQH7HN7.mjs +460 -0
- package/dist/lib/node-esm/intent-resolver-OIQH7HN7.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/react-root-WKJWCHXR.mjs +29 -0
- package/dist/lib/node-esm/react-root-WKJWCHXR.mjs.map +7 -0
- package/dist/lib/node-esm/react-surface-RVEHOSAD.mjs +239 -0
- package/dist/lib/node-esm/react-surface-RVEHOSAD.mjs.map +7 -0
- package/dist/lib/node-esm/settings-WLVEO4JM.mjs +25 -0
- package/dist/lib/node-esm/settings-WLVEO4JM.mjs.map +7 -0
- package/dist/lib/node-esm/spaces-ready-ITGYYT5A.mjs +201 -0
- package/dist/lib/node-esm/spaces-ready-ITGYYT5A.mjs.map +7 -0
- package/dist/lib/node-esm/state-BMISGQ2O.mjs +48 -0
- package/dist/lib/node-esm/state-BMISGQ2O.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +14 -5
- package/dist/types/src/SpacePlugin.d.ts +1 -24
- package/dist/types/src/SpacePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-serializer.d.ts +4 -0
- package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -0
- package/dist/types/src/capabilities/capabilities.d.ts +15 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/identity-created.d.ts +4 -0
- package/dist/types/src/capabilities/identity-created.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +195 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +8 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-root.d.ts +7 -0
- package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +7 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings.d.ts.map +1 -0
- package/dist/types/src/capabilities/spaces-ready.d.ts +4 -0
- package/dist/types/src/capabilities/spaces-ready.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +5 -0
- package/dist/types/src/capabilities/state.d.ts.map +1 -0
- package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts +7 -0
- package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts.map +1 -0
- package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts +8 -0
- package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts.map +1 -0
- package/dist/types/src/components/AdvancedObjectSettings/index.d.ts +2 -0
- package/dist/types/src/components/AdvancedObjectSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/AwaitingObject.d.ts.map +1 -1
- package/dist/types/src/components/BaseObjectSettings.d.ts +7 -0
- package/dist/types/src/components/BaseObjectSettings.d.ts.map +1 -0
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +5 -4
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +5 -6
- package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +1 -0
- package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
- package/dist/types/src/components/JoinDialog.d.ts +1 -0
- package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
- package/dist/types/src/components/PopoverRenameObject.d.ts +1 -0
- package/dist/types/src/components/PopoverRenameObject.d.ts.map +1 -1
- package/dist/types/src/components/PopoverRenameSpace.d.ts +1 -0
- package/dist/types/src/components/PopoverRenameSpace.d.ts.map +1 -1
- package/dist/types/src/components/ShareSpaceButton.d.ts.map +1 -1
- package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
- package/dist/types/src/components/SpacePresence.d.ts +9 -6
- package/dist/types/src/components/SpacePresence.d.ts.map +1 -1
- package/dist/types/src/components/SpacePresence.stories.d.ts +1 -1
- package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts +4 -3
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +3 -3
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts +2 -2
- package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +5 -0
- package/dist/types/src/events.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/usePath.d.ts +11 -0
- package/dist/types/src/hooks/usePath.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +1 -27
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +18 -3
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/collection.d.ts +8 -12
- package/dist/types/src/types/collection.d.ts.map +1 -1
- package/dist/types/src/types/thread.d.ts +180 -186
- package/dist/types/src/types/thread.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +228 -16
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +9 -8
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +38 -46
- package/src/SpacePlugin.tsx +119 -1541
- package/src/capabilities/app-graph-builder.ts +392 -0
- package/src/capabilities/app-graph-serializer.ts +73 -0
- package/src/capabilities/capabilities.ts +23 -0
- package/src/capabilities/identity-created.ts +26 -0
- package/src/capabilities/index.ts +17 -0
- package/src/capabilities/intent-resolver.ts +420 -0
- package/src/capabilities/react-root.tsx +20 -0
- package/src/capabilities/react-surface.tsx +234 -0
- package/src/capabilities/settings.ts +17 -0
- package/src/capabilities/spaces-ready.ts +231 -0
- package/src/capabilities/state.ts +45 -0
- package/src/components/AdvancedObjectSettings/AdvancedObjectSettings.tsx +72 -0
- package/src/components/AdvancedObjectSettings/ForeignKeys.tsx +51 -0
- package/src/components/AdvancedObjectSettings/index.ts +5 -0
- package/src/components/AwaitingObject.tsx +15 -19
- package/src/components/{DefaultObjectSettings.tsx → BaseObjectSettings.tsx} +2 -2
- package/src/components/CreateDialog/CreateObjectDialog.tsx +36 -25
- package/src/components/CreateDialog/CreateObjectPanel.tsx +61 -24
- package/src/components/CreateDialog/CreateSpaceDialog.tsx +10 -14
- package/src/components/JoinDialog.tsx +18 -34
- package/src/components/PersistenceStatus.tsx +1 -1
- package/src/components/PopoverRenameObject.tsx +2 -0
- package/src/components/PopoverRenameSpace.tsx +2 -0
- package/src/components/ShareSpaceButton.tsx +5 -4
- package/src/components/SpacePluginSettings.tsx +2 -13
- package/src/components/SpacePresence.stories.tsx +25 -17
- package/src/components/SpacePresence.tsx +42 -21
- package/src/components/SpaceSettings/SpaceSettingsDialog.stories.tsx +2 -3
- package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +3 -1
- package/src/components/SpaceSettings/SpaceSettingsPanel.stories.tsx +7 -5
- package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +6 -5
- package/src/components/SyncStatus/InlineSyncStatus.tsx +37 -27
- package/src/components/SyncStatus/SyncStatusDetail.stories.tsx +55 -51
- package/src/components/index.ts +2 -1
- package/src/events.ts +12 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/usePath.ts +44 -0
- package/src/index.ts +3 -7
- package/src/meta.ts +1 -29
- package/src/translations.ts +7 -2
- package/src/types/collection.ts +3 -3
- package/src/types/thread.ts +6 -6
- package/src/types/types.ts +177 -42
- package/src/util.tsx +77 -64
- package/dist/lib/browser/chunk-FTKV32QZ.mjs +0 -43
- package/dist/lib/browser/chunk-FTKV32QZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-MWKXNS5S.mjs +0 -124
- package/dist/lib/browser/chunk-MWKXNS5S.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -15
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/lib/node/chunk-6SNOZF7Y.cjs +0 -152
- package/dist/lib/node/chunk-6SNOZF7Y.cjs.map +0 -7
- package/dist/lib/node/chunk-QNVEU2UD.cjs +0 -69
- package/dist/lib/node/chunk-QNVEU2UD.cjs.map +0 -7
- package/dist/lib/node/meta.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-OHEAWSCA.mjs +0 -126
- package/dist/lib/node-esm/chunk-OHEAWSCA.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-UMV7XREB.mjs +0 -45
- package/dist/lib/node-esm/chunk-UMV7XREB.mjs.map +0 -7
- package/dist/lib/node-esm/meta.mjs +0 -16
- package/dist/lib/node-esm/meta.mjs.map +0 -7
- package/dist/types/src/components/DefaultObjectSettings.d.ts +0 -7
- package/dist/types/src/components/DefaultObjectSettings.d.ts.map +0 -1
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts +0 -6
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts.map +0 -1
- package/src/components/SyncStatus/InlineSyncStatus.stories.tsx +0 -57
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { contributes, createIntent, openIds, type PluginsContext, Capabilities } from '@dxos/app-framework';
|
|
6
|
+
import { EventSubscriptions } from '@dxos/async';
|
|
7
|
+
import { Expando } from '@dxos/echo-schema';
|
|
8
|
+
import { scheduledEffect } from '@dxos/echo-signals/core';
|
|
9
|
+
import { create } from '@dxos/live-object';
|
|
10
|
+
import { log } from '@dxos/log';
|
|
11
|
+
import { AttentionCapabilities } from '@dxos/plugin-attention';
|
|
12
|
+
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
13
|
+
import { EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
14
|
+
import { PublicKey } from '@dxos/react-client';
|
|
15
|
+
import { Filter, FQ_ID_LENGTH, parseFullyQualifiedId, SpaceState } from '@dxos/react-client/echo';
|
|
16
|
+
import { ComplexMap, reduceGroupBy } from '@dxos/util';
|
|
17
|
+
|
|
18
|
+
import { SpaceCapabilities } from './capabilities';
|
|
19
|
+
import { SpaceAction } from '../types';
|
|
20
|
+
import { COMPOSER_SPACE_LOCK, SHARED } from '../util';
|
|
21
|
+
|
|
22
|
+
const ACTIVE_NODE_BROADCAST_INTERVAL = 30_000;
|
|
23
|
+
const WAIT_FOR_OBJECT_TIMEOUT = 1000;
|
|
24
|
+
|
|
25
|
+
export default async (context: PluginsContext) => {
|
|
26
|
+
const subscriptions = new EventSubscriptions();
|
|
27
|
+
const spaceSubscriptions = new EventSubscriptions();
|
|
28
|
+
|
|
29
|
+
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
30
|
+
const { graph } = context.requestCapability(Capabilities.AppGraph);
|
|
31
|
+
const layout = context.requestCapability(Capabilities.Layout);
|
|
32
|
+
const location = context.requestCapability(Capabilities.Location);
|
|
33
|
+
const attention = context.requestCapability(AttentionCapabilities.Attention);
|
|
34
|
+
const state = context.requestCapability(SpaceCapabilities.MutableState);
|
|
35
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
36
|
+
|
|
37
|
+
const defaultSpace = client.spaces.default;
|
|
38
|
+
await defaultSpace.waitUntilReady();
|
|
39
|
+
|
|
40
|
+
// Initialize space sharing lock in default space.
|
|
41
|
+
if (typeof defaultSpace.properties[COMPOSER_SPACE_LOCK] !== 'boolean') {
|
|
42
|
+
defaultSpace.properties[COMPOSER_SPACE_LOCK] = true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const {
|
|
46
|
+
objects: [spacesOrder],
|
|
47
|
+
} = await defaultSpace.db.query(Filter.schema(Expando, { key: SHARED })).run();
|
|
48
|
+
if (!spacesOrder) {
|
|
49
|
+
// TODO(wittjosiah): Cannot be a Folder because Spaces are not TypedObjects so can't be saved in the database.
|
|
50
|
+
// Instead, we store order as an array of space ids.
|
|
51
|
+
defaultSpace.db.add(create({ key: SHARED, order: [] }));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Await missing objects.
|
|
55
|
+
subscriptions.add(
|
|
56
|
+
scheduledEffect(
|
|
57
|
+
() => ({
|
|
58
|
+
layoutMode: layout.layoutMode,
|
|
59
|
+
soloPart: location.active.solo?.[0],
|
|
60
|
+
}),
|
|
61
|
+
({ layoutMode, soloPart }) => {
|
|
62
|
+
if (layoutMode !== 'solo' || !soloPart) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const node = graph.findNode(soloPart.id);
|
|
67
|
+
if (!node && soloPart.id.length === FQ_ID_LENGTH) {
|
|
68
|
+
const timeout = setTimeout(async () => {
|
|
69
|
+
const node = graph.findNode(soloPart.id);
|
|
70
|
+
if (!node) {
|
|
71
|
+
await dispatch(createIntent(SpaceAction.WaitForObject, { id: soloPart.id }));
|
|
72
|
+
}
|
|
73
|
+
}, WAIT_FOR_OBJECT_TIMEOUT);
|
|
74
|
+
|
|
75
|
+
return () => clearTimeout(timeout);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Cache space names.
|
|
82
|
+
subscriptions.add(
|
|
83
|
+
client.spaces.subscribe(async (spaces) => {
|
|
84
|
+
// TODO(wittjosiah): Remove. This is a hack to be able to migrate the default space properties.
|
|
85
|
+
if (defaultSpace.state.get() === SpaceState.SPACE_REQUIRES_MIGRATION) {
|
|
86
|
+
await defaultSpace.internal.migrate();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
spaces
|
|
90
|
+
.filter((space) => space.state.get() === SpaceState.SPACE_READY)
|
|
91
|
+
.forEach((space) => {
|
|
92
|
+
subscriptions.add(
|
|
93
|
+
scheduledEffect(
|
|
94
|
+
() => ({ name: space.properties.name }),
|
|
95
|
+
({ name }) => (state.spaceNames[space.id] = name),
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
}).unsubscribe,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Broadcast active node to other peers in the space.
|
|
103
|
+
subscriptions.add(
|
|
104
|
+
scheduledEffect(
|
|
105
|
+
() => ({
|
|
106
|
+
open: openIds(location.active, layout.layoutMode === 'solo' ? ['solo'] : ['main']),
|
|
107
|
+
closed: [...location.closed],
|
|
108
|
+
}),
|
|
109
|
+
({ open, closed }) => {
|
|
110
|
+
const send = () => {
|
|
111
|
+
const spaces = client.spaces.get();
|
|
112
|
+
const identity = client.halo.identity.get();
|
|
113
|
+
if (identity && location.active) {
|
|
114
|
+
// Group parts by space for efficient messaging.
|
|
115
|
+
const idsBySpace = reduceGroupBy(open, (id) => {
|
|
116
|
+
try {
|
|
117
|
+
const [spaceId] = parseFullyQualifiedId(id);
|
|
118
|
+
return spaceId;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const removedBySpace = reduceGroupBy(closed, (id) => {
|
|
125
|
+
try {
|
|
126
|
+
const [spaceId] = parseFullyQualifiedId(id);
|
|
127
|
+
return spaceId;
|
|
128
|
+
} catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// NOTE: Ensure all spaces are included so that we send the correct `removed` object arrays.
|
|
134
|
+
for (const space of spaces) {
|
|
135
|
+
if (!idsBySpace.has(space.id)) {
|
|
136
|
+
idsBySpace.set(space.id, []);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (const [spaceId, added] of idsBySpace) {
|
|
141
|
+
const removed = removedBySpace.get(spaceId) ?? [];
|
|
142
|
+
const space = spaces.find((space) => space.id === spaceId);
|
|
143
|
+
if (!space) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void space
|
|
148
|
+
.postMessage('viewing', {
|
|
149
|
+
identityKey: identity.identityKey.toHex(),
|
|
150
|
+
attended: attention.current ? [...attention.current] : [],
|
|
151
|
+
added,
|
|
152
|
+
removed,
|
|
153
|
+
})
|
|
154
|
+
// TODO(burdon): This seems defensive; why would this fail? Backoff interval.
|
|
155
|
+
.catch((err) => {
|
|
156
|
+
log.warn('Failed to broadcast active node for presence.', { err: err.message });
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
send();
|
|
163
|
+
// Send at interval to allow peers to expire entries if they become disconnected.
|
|
164
|
+
const interval = setInterval(() => send(), ACTIVE_NODE_BROADCAST_INTERVAL);
|
|
165
|
+
return () => clearInterval(interval);
|
|
166
|
+
},
|
|
167
|
+
),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// Listen for active nodes from other peers in the space.
|
|
171
|
+
subscriptions.add(
|
|
172
|
+
client.spaces.subscribe((spaces) => {
|
|
173
|
+
spaceSubscriptions.clear();
|
|
174
|
+
spaces.forEach((space) => {
|
|
175
|
+
spaceSubscriptions.add(
|
|
176
|
+
space.listen('viewing', (message) => {
|
|
177
|
+
const { added, removed, attended } = message.payload;
|
|
178
|
+
|
|
179
|
+
const identityKey = PublicKey.safeFrom(message.payload.identityKey);
|
|
180
|
+
const currentIdentity = client.halo.identity.get();
|
|
181
|
+
if (
|
|
182
|
+
identityKey &&
|
|
183
|
+
!currentIdentity?.identityKey.equals(identityKey) &&
|
|
184
|
+
Array.isArray(added) &&
|
|
185
|
+
Array.isArray(removed)
|
|
186
|
+
) {
|
|
187
|
+
added.forEach((id) => {
|
|
188
|
+
if (typeof id === 'string') {
|
|
189
|
+
if (!(id in state.viewersByObject)) {
|
|
190
|
+
state.viewersByObject[id] = new ComplexMap(PublicKey.hash);
|
|
191
|
+
}
|
|
192
|
+
state.viewersByObject[id]!.set(identityKey, {
|
|
193
|
+
lastSeen: Date.now(),
|
|
194
|
+
currentlyAttended: new Set(attended).has(id),
|
|
195
|
+
});
|
|
196
|
+
if (!state.viewersByIdentity.has(identityKey)) {
|
|
197
|
+
state.viewersByIdentity.set(identityKey, new Set());
|
|
198
|
+
}
|
|
199
|
+
state.viewersByIdentity.get(identityKey)!.add(id);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
removed.forEach((id) => {
|
|
204
|
+
if (typeof id === 'string') {
|
|
205
|
+
state.viewersByObject[id]?.delete(identityKey);
|
|
206
|
+
state.viewersByIdentity.get(identityKey)?.delete(id);
|
|
207
|
+
// It’s okay for these to be empty sets/maps, reduces churn.
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
}).unsubscribe,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
// Enable edge replication for all spaces.
|
|
218
|
+
try {
|
|
219
|
+
await Promise.all(
|
|
220
|
+
client.spaces.get().map((space) => space.internal.setEdgeReplicationPreference(EdgeReplicationSetting.ENABLED)),
|
|
221
|
+
);
|
|
222
|
+
state.enabledEdgeReplication = true;
|
|
223
|
+
} catch (err) {
|
|
224
|
+
log.catch(err);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return contributes(Capabilities.Null, null, () => {
|
|
228
|
+
spaceSubscriptions.clear();
|
|
229
|
+
subscriptions.clear();
|
|
230
|
+
});
|
|
231
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { effect } from '@preact/signals-core';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
|
|
8
|
+
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { LocalStorageStore } from '@dxos/local-storage';
|
|
10
|
+
import { ComplexMap } from '@dxos/util';
|
|
11
|
+
|
|
12
|
+
import { SpaceCapabilities } from './capabilities';
|
|
13
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
14
|
+
import { type PluginState } from '../types';
|
|
15
|
+
|
|
16
|
+
export default (context: PluginsContext) => {
|
|
17
|
+
const state = new LocalStorageStore<PluginState>(SPACE_PLUGIN, {
|
|
18
|
+
awaiting: undefined,
|
|
19
|
+
spaceNames: {},
|
|
20
|
+
viewersByObject: {},
|
|
21
|
+
// TODO(wittjosiah): Stop using (Complex)Map inside reactive object.
|
|
22
|
+
viewersByIdentity: new ComplexMap(PublicKey.hash),
|
|
23
|
+
sdkMigrationRunning: {},
|
|
24
|
+
navigableCollections: false,
|
|
25
|
+
enabledEdgeReplication: false,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
state
|
|
29
|
+
.prop({ key: 'spaceNames', type: LocalStorageStore.json<Record<string, string>>() })
|
|
30
|
+
.prop({ key: 'enabledEdgeReplication', type: LocalStorageStore.bool() });
|
|
31
|
+
|
|
32
|
+
const manager = context.requestCapability(Capabilities.PluginManager);
|
|
33
|
+
const unsubscribe = effect(() => {
|
|
34
|
+
// TODO(wittjosiah): Find a way to make this capability-based.
|
|
35
|
+
const enabled = manager.enabled.includes('dxos.org/plugin/stack');
|
|
36
|
+
if (enabled !== state.values.navigableCollections) {
|
|
37
|
+
state.values.navigableCollections = enabled;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return contributes(SpaceCapabilities.State, state.values, () => {
|
|
42
|
+
unsubscribe();
|
|
43
|
+
state.close();
|
|
44
|
+
});
|
|
45
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type ForeignKey, ForeignKeySchema } from '@dxos/echo-schema';
|
|
8
|
+
import { getMeta, type ReactiveEchoObject } from '@dxos/react-client/echo';
|
|
9
|
+
import { IconButton, useTranslation, Separator } from '@dxos/react-ui';
|
|
10
|
+
import { Form } from '@dxos/react-ui-form';
|
|
11
|
+
|
|
12
|
+
import { ForeignKeys } from './ForeignKeys';
|
|
13
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
14
|
+
|
|
15
|
+
const initialValues = {
|
|
16
|
+
source: '',
|
|
17
|
+
id: '',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type AdvancedObjectSettingsProps = {
|
|
21
|
+
object: ReactiveEchoObject<any>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const AdvancedObjectSettings = ({ object }: AdvancedObjectSettingsProps) => {
|
|
25
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
26
|
+
const [adding, setAdding] = useState(false);
|
|
27
|
+
const keys = getMeta(object).keys;
|
|
28
|
+
|
|
29
|
+
const handleNew = useCallback(() => setAdding(true), []);
|
|
30
|
+
const handleCancel = useCallback(() => setAdding(false), []);
|
|
31
|
+
const handleSave = useCallback(
|
|
32
|
+
(key: ForeignKey) => {
|
|
33
|
+
const index = keys.findIndex(({ source, id }) => source === key.source && id === key.id);
|
|
34
|
+
if (index === -1) {
|
|
35
|
+
keys.push(key);
|
|
36
|
+
}
|
|
37
|
+
setAdding(false);
|
|
38
|
+
},
|
|
39
|
+
[keys],
|
|
40
|
+
);
|
|
41
|
+
const handleDelete = useCallback(
|
|
42
|
+
(key: ForeignKey) => {
|
|
43
|
+
const index = keys.findIndex(({ source, id }) => source === key.source && id === key.id);
|
|
44
|
+
if (index !== -1) {
|
|
45
|
+
keys.splice(index, 1);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[keys],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// TODO(wittjosiah): This should be wrapped in an "Advanced" accordion.
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<Separator />
|
|
55
|
+
<div className='p-2 flex flex-col gap-4'>
|
|
56
|
+
<h2>{t('advanced settings label')}</h2>
|
|
57
|
+
<div className='flex items-center'>
|
|
58
|
+
<h3 className='text-sm font-semibold'>{t('foreign keys')}</h3>
|
|
59
|
+
<div className='grow' />
|
|
60
|
+
<IconButton
|
|
61
|
+
classNames={adding && 'invisible'}
|
|
62
|
+
icon='ph--plus--regular'
|
|
63
|
+
label={t('add key')}
|
|
64
|
+
onClick={handleNew}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
{!adding && <ForeignKeys keys={keys} onDelete={handleDelete} />}
|
|
68
|
+
</div>
|
|
69
|
+
{adding && <Form schema={ForeignKeySchema} values={initialValues} onSave={handleSave} onCancel={handleCancel} />}
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type ForeignKey } from '@dxos/echo-schema';
|
|
8
|
+
import { IconButton, List, ListItem, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
|
|
10
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
11
|
+
|
|
12
|
+
export type ForeignKeysProps = {
|
|
13
|
+
keys: ForeignKey[];
|
|
14
|
+
onDelete?: (key: ForeignKey) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// TODO(wittjosiah): This is a clone of `TokenManager`. Consider a form variant for arrays of read-only objects.
|
|
18
|
+
export const ForeignKeys = ({ keys, onDelete }: ForeignKeysProps) => {
|
|
19
|
+
return (
|
|
20
|
+
<List classNames='flex flex-col gap-2'>
|
|
21
|
+
{keys.map((key) => (
|
|
22
|
+
<KeyItem key={key.id} forignKey={key} onDelete={onDelete} />
|
|
23
|
+
))}
|
|
24
|
+
</List>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type KeyItemProps = {
|
|
29
|
+
forignKey: ForeignKey;
|
|
30
|
+
onDelete?: (key: ForeignKey) => void;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const KeyItem = ({ forignKey, onDelete }: KeyItemProps) => {
|
|
34
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
35
|
+
|
|
36
|
+
const handleDelete = useCallback(() => {
|
|
37
|
+
onDelete?.(forignKey);
|
|
38
|
+
}, [forignKey, onDelete]);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ListItem.Root classNames='px-2'>
|
|
42
|
+
<ListItem.Heading classNames='flex flex-col grow truncate'>
|
|
43
|
+
<div>{forignKey.source}</div>
|
|
44
|
+
<div className='text-description text-sm truncate'>{forignKey.id}</div>
|
|
45
|
+
</ListItem.Heading>
|
|
46
|
+
<ListItem.Endcap>
|
|
47
|
+
<IconButton iconOnly icon='ph--x--regular' variant='ghost' label={t('delete key')} onClick={handleDelete} />
|
|
48
|
+
</ListItem.Endcap>
|
|
49
|
+
</ListItem.Root>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { CheckCircle, CircleDashed, CircleNotch } from '@phosphor-icons/react';
|
|
6
|
-
import React, { useEffect, useState } from 'react';
|
|
6
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { NavigationAction, useIntentDispatcher, createIntent, useCapability, Capabilities } from '@dxos/app-framework';
|
|
9
9
|
import { useClient } from '@dxos/react-client';
|
|
10
10
|
import { Filter, fullyQualifiedId, useQuery } from '@dxos/react-client/echo';
|
|
11
11
|
import { Button, Toast, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
15
|
+
import { SpaceAction } from '../types';
|
|
15
16
|
|
|
16
17
|
const WAIT_FOR_OBJECT_TIMEOUT = 180e3; // 3 minutes
|
|
17
18
|
const TOAST_TIMEOUT = 240e3; // 4 minutes
|
|
@@ -21,8 +22,8 @@ export const AwaitingObject = ({ id }: { id: string }) => {
|
|
|
21
22
|
const [waiting, setWaiting] = useState(true);
|
|
22
23
|
const [found, setFound] = useState(false);
|
|
23
24
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
24
|
-
const
|
|
25
|
-
const
|
|
25
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
26
|
+
const location = useCapability(Capabilities.Location);
|
|
26
27
|
|
|
27
28
|
const client = useClient();
|
|
28
29
|
const objects = useQuery(client.spaces, Filter.all());
|
|
@@ -43,26 +44,21 @@ export const AwaitingObject = ({ id }: { id: string }) => {
|
|
|
43
44
|
if (objects.findIndex((object) => fullyQualifiedId(object) === id) > -1) {
|
|
44
45
|
setFound(true);
|
|
45
46
|
|
|
46
|
-
if (
|
|
47
|
+
if (location.active.solo?.[0].id === id) {
|
|
47
48
|
setOpen(false);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
}, [id, objects,
|
|
51
|
+
}, [id, objects, location]);
|
|
51
52
|
|
|
52
|
-
const handleClose =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
data: { id: undefined },
|
|
57
|
-
});
|
|
53
|
+
const handleClose = useCallback(
|
|
54
|
+
async () => dispatch(createIntent(SpaceAction.WaitForObject, { id: undefined })),
|
|
55
|
+
[dispatch],
|
|
56
|
+
);
|
|
58
57
|
|
|
59
|
-
const handleNavigate = () => {
|
|
60
|
-
void
|
|
61
|
-
action: NavigationAction.OPEN,
|
|
62
|
-
data: { activeParts: { main: [id] } },
|
|
63
|
-
});
|
|
58
|
+
const handleNavigate = useCallback(() => {
|
|
59
|
+
void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [id] } }));
|
|
64
60
|
void handleClose();
|
|
65
|
-
};
|
|
61
|
+
}, [id, handleClose, dispatch]);
|
|
66
62
|
|
|
67
63
|
return (
|
|
68
64
|
<Toast.Root open={open} duration={TOAST_TIMEOUT} onOpenChange={setOpen}>
|
|
@@ -9,11 +9,11 @@ import { Input, useTranslation } from '@dxos/react-ui';
|
|
|
9
9
|
|
|
10
10
|
import { SPACE_PLUGIN } from '../meta';
|
|
11
11
|
|
|
12
|
-
export type
|
|
12
|
+
export type BaseObjectSettingsProps = {
|
|
13
13
|
object: ReactiveEchoObject<any>;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const BaseObjectSettings = ({ object }: BaseObjectSettingsProps) => {
|
|
17
17
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
18
18
|
// TODO(burdon): Standardize forms.
|
|
19
19
|
return (
|
|
@@ -2,20 +2,30 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { pipe } from 'effect';
|
|
5
6
|
import React, { useCallback, useRef } from 'react';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { chain, createIntent, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
9
|
import { useClient } from '@dxos/react-client';
|
|
9
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
getSpace,
|
|
12
|
+
isReactiveObject,
|
|
13
|
+
isSpace,
|
|
14
|
+
type ReactiveObject,
|
|
15
|
+
type TypedObject,
|
|
16
|
+
useSpaces,
|
|
17
|
+
} from '@dxos/react-client/echo';
|
|
10
18
|
import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
|
|
11
19
|
|
|
12
20
|
import { CreateObjectPanel, type CreateObjectPanelProps } from './CreateObjectPanel';
|
|
13
|
-
import { SPACE_PLUGIN
|
|
14
|
-
import { CollectionType } from '../../types';
|
|
21
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
22
|
+
import { CollectionType, SpaceAction } from '../../types';
|
|
23
|
+
|
|
24
|
+
export const CREATE_OBJECT_DIALOG = `${SPACE_PLUGIN}/CreateObjectDialog`;
|
|
15
25
|
|
|
16
26
|
export type CreateObjectDialogProps = Pick<CreateObjectPanelProps, 'schemas' | 'target' | 'typename' | 'name'> & {
|
|
17
|
-
resolve?:
|
|
18
|
-
|
|
27
|
+
resolve?: (typename: string) => Record<string, any>;
|
|
28
|
+
shouldNavigate?: (object: ReactiveObject<any>) => boolean;
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
export const CreateObjectDialog = ({
|
|
@@ -23,28 +33,30 @@ export const CreateObjectDialog = ({
|
|
|
23
33
|
target,
|
|
24
34
|
typename,
|
|
25
35
|
name,
|
|
26
|
-
|
|
36
|
+
shouldNavigate: _shouldNavigate,
|
|
27
37
|
resolve,
|
|
28
38
|
}: CreateObjectDialogProps) => {
|
|
29
39
|
const closeRef = useRef<HTMLButtonElement | null>(null);
|
|
30
40
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
31
41
|
const client = useClient();
|
|
32
42
|
const spaces = useSpaces();
|
|
33
|
-
const dispatch = useIntentDispatcher();
|
|
43
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
34
44
|
|
|
35
45
|
const handleCreateObject = useCallback(
|
|
36
46
|
async ({
|
|
37
47
|
schema,
|
|
38
48
|
target: _target,
|
|
39
|
-
|
|
49
|
+
data,
|
|
40
50
|
}: {
|
|
41
|
-
schema:
|
|
51
|
+
schema: TypedObject;
|
|
42
52
|
target: CreateObjectPanelProps['target'];
|
|
43
|
-
|
|
53
|
+
data?: Record<string, any>;
|
|
44
54
|
}) => {
|
|
45
|
-
const target = isSpace(_target)
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const target = isSpace(_target)
|
|
56
|
+
? (_target.properties[CollectionType.typename]?.target as CollectionType | undefined)
|
|
57
|
+
: _target;
|
|
58
|
+
const createObjectIntent = resolve?.(schema.typename)?.createObject;
|
|
59
|
+
if (!createObjectIntent || !target) {
|
|
48
60
|
// TODO(wittjosiah): UI feedback.
|
|
49
61
|
return;
|
|
50
62
|
}
|
|
@@ -53,17 +65,16 @@ export const CreateObjectDialog = ({
|
|
|
53
65
|
closeRef.current?.click();
|
|
54
66
|
|
|
55
67
|
const space = isSpace(target) ? target : getSpace(target);
|
|
56
|
-
const result = await dispatch(
|
|
57
|
-
const object = result?.
|
|
68
|
+
const result = await dispatch(createObjectIntent(data, { space }));
|
|
69
|
+
const object = result.data?.object;
|
|
58
70
|
if (isReactiveObject(object)) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
]);
|
|
71
|
+
const addObjectIntent = createIntent(SpaceAction.AddObject, { target, object });
|
|
72
|
+
const shouldNavigate = _shouldNavigate ?? (() => true);
|
|
73
|
+
if (shouldNavigate(object)) {
|
|
74
|
+
await dispatch(pipe(addObjectIntent, chain(NavigationAction.Open, {})));
|
|
75
|
+
} else {
|
|
76
|
+
await dispatch(addObjectIntent);
|
|
77
|
+
}
|
|
67
78
|
}
|
|
68
79
|
},
|
|
69
80
|
[dispatch, resolve],
|
|
@@ -73,7 +84,7 @@ export const CreateObjectDialog = ({
|
|
|
73
84
|
// TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
|
|
74
85
|
// Consider factoring it out to the tabs package.
|
|
75
86
|
<Dialog.Content classNames='p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden'>
|
|
76
|
-
<div role='none' className='flex justify-between pbs-
|
|
87
|
+
<div role='none' className='flex justify-between pbs-2 pis-2 pie-2 @md:pbs-4 @md:pis-4 @md:pie-4'>
|
|
77
88
|
<Dialog.Title>{t('create object dialog title')}</Dialog.Title>
|
|
78
89
|
<Dialog.Close asChild>
|
|
79
90
|
<Button ref={closeRef} density='fine' variant='ghost' autoFocus>
|