@dxos/plugin-space 0.6.11 → 0.6.12-main.568932b
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/{chunk-DTVUOG2C.mjs → chunk-NMD7OZMX.mjs} +22 -4
- package/dist/lib/browser/chunk-NMD7OZMX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +500 -187
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +7 -3
- package/dist/lib/node/{chunk-CVZPI2P3.cjs → chunk-K7CSJ7HL.cjs} +28 -8
- package/dist/lib/node/chunk-K7CSJ7HL.cjs.map +7 -0
- package/dist/lib/node/index.cjs +588 -279
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +14 -10
- package/dist/lib/node/types/index.cjs.map +2 -2
- package/dist/lib/node-esm/chunk-GM2YUC77.mjs +37 -0
- package/dist/lib/node-esm/chunk-GM2YUC77.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-P73EVC4A.mjs +115 -0
- package/dist/lib/node-esm/chunk-P73EVC4A.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +2954 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/meta.mjs +14 -0
- package/dist/lib/node-esm/meta.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +26 -0
- package/dist/lib/node-esm/types/index.mjs.map +7 -0
- package/dist/types/src/SpacePlugin.d.ts.map +1 -1
- package/dist/types/src/components/MenuFooter.d.ts.map +1 -1
- package/dist/types/src/components/SaveStatus.d.ts +3 -0
- package/dist/types/src/components/SaveStatus.d.ts.map +1 -0
- package/dist/types/src/components/ShareSpaceButton.stories.d.ts +2 -0
- package/dist/types/src/components/ShareSpaceButton.stories.d.ts.map +1 -1
- package/dist/types/src/components/SpaceMain/SpaceMain.d.ts.map +1 -1
- package/dist/types/src/components/SpacePresence.stories.d.ts +2 -0
- package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +13 -0
- package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -0
- package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +115 -0
- package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -0
- package/dist/types/src/components/SyncStatus/index.d.ts +2 -0
- package/dist/types/src/components/SyncStatus/index.d.ts.map +1 -0
- package/dist/types/src/components/SyncStatus/types.d.ts +14 -0
- package/dist/types/src/components/SyncStatus/types.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/thread.d.ts +13 -0
- package/dist/types/src/types/thread.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +18 -1
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +1 -4
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +43 -36
- package/src/SpacePlugin.tsx +43 -24
- package/src/components/MenuFooter.tsx +1 -0
- package/src/components/SaveStatus.tsx +95 -0
- package/src/components/SpaceMain/SpaceMain.tsx +1 -22
- package/src/components/SpacePresence.tsx +1 -1
- package/src/components/SpaceSettings.tsx +32 -3
- package/src/components/SyncStatus/SyncStatus.stories.tsx +62 -0
- package/src/components/SyncStatus/SyncStatus.tsx +188 -0
- package/src/components/SyncStatus/index.ts +5 -0
- package/src/components/SyncStatus/types.ts +77 -0
- package/src/components/index.ts +2 -0
- package/src/translations.ts +2 -0
- package/src/types/collection.ts +1 -1
- package/src/types/thread.ts +10 -1
- package/src/types/types.ts +25 -1
- package/src/util.tsx +15 -50
- package/dist/lib/browser/chunk-DTVUOG2C.mjs.map +0 -7
- package/dist/lib/node/chunk-CVZPI2P3.cjs.map +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-space",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.12-main.568932b",
|
|
4
4
|
"description": "DXOS Surface plugin for DXOS ECHO Spaces",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -10,21 +10,24 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"browser": "./dist/lib/browser/index.mjs",
|
|
12
12
|
"node": {
|
|
13
|
-
"
|
|
13
|
+
"require": "./dist/lib/node/index.cjs",
|
|
14
|
+
"default": "./dist/lib/node-esm/index.mjs"
|
|
14
15
|
},
|
|
15
16
|
"types": "./dist/types/src/index.d.ts"
|
|
16
17
|
},
|
|
17
18
|
"./meta": {
|
|
18
19
|
"browser": "./dist/lib/browser/meta.mjs",
|
|
19
20
|
"node": {
|
|
20
|
-
"
|
|
21
|
+
"require": "./dist/lib/node/meta.cjs",
|
|
22
|
+
"default": "./dist/lib/node-esm/meta.mjs"
|
|
21
23
|
},
|
|
22
24
|
"types": "./dist/types/src/meta.d.ts"
|
|
23
25
|
},
|
|
24
26
|
"./types": {
|
|
25
27
|
"browser": "./dist/lib/browser/types/index.mjs",
|
|
26
28
|
"node": {
|
|
27
|
-
"
|
|
29
|
+
"require": "./dist/lib/node/types/index.cjs",
|
|
30
|
+
"default": "./dist/lib/node-esm/types/index.mjs"
|
|
28
31
|
},
|
|
29
32
|
"types": "./dist/types/src/types/index.d.ts"
|
|
30
33
|
}
|
|
@@ -45,34 +48,39 @@
|
|
|
45
48
|
"src"
|
|
46
49
|
],
|
|
47
50
|
"dependencies": {
|
|
51
|
+
"@effect/schema": "^0.75.1",
|
|
48
52
|
"@preact/signals-core": "^1.6.0",
|
|
49
53
|
"jszip": "^3.10.1",
|
|
50
54
|
"localforage": "^1.10.0",
|
|
51
55
|
"lodash.get": "^4.4.2",
|
|
52
56
|
"react-drag-drop-files": "^2.3.8",
|
|
53
57
|
"react-is": "~18.2.0",
|
|
54
|
-
"@dxos/app-framework": "0.6.
|
|
55
|
-
"@dxos/async": "0.6.
|
|
56
|
-
"@dxos/automerge": "0.6.
|
|
57
|
-
"@dxos/
|
|
58
|
-
"@dxos/
|
|
59
|
-
"@dxos/
|
|
60
|
-
"@dxos/invariant": "0.6.
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/migrations": "0.6.
|
|
65
|
-
"@dxos/plugin-
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/plugin-
|
|
68
|
-
"@dxos/plugin-metadata": "0.6.
|
|
69
|
-
"@dxos/plugin-observability": "0.6.
|
|
70
|
-
"@dxos/plugin-
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/react-
|
|
75
|
-
"@dxos/
|
|
58
|
+
"@dxos/app-framework": "0.6.12-main.568932b",
|
|
59
|
+
"@dxos/async": "0.6.12-main.568932b",
|
|
60
|
+
"@dxos/automerge": "0.6.12-main.568932b",
|
|
61
|
+
"@dxos/client": "0.6.12-main.568932b",
|
|
62
|
+
"@dxos/display-name": "0.6.12-main.568932b",
|
|
63
|
+
"@dxos/context": "0.6.12-main.568932b",
|
|
64
|
+
"@dxos/invariant": "0.6.12-main.568932b",
|
|
65
|
+
"@dxos/echo-schema": "0.6.12-main.568932b",
|
|
66
|
+
"@dxos/local-storage": "0.6.12-main.568932b",
|
|
67
|
+
"@dxos/keys": "0.6.12-main.568932b",
|
|
68
|
+
"@dxos/migrations": "0.6.12-main.568932b",
|
|
69
|
+
"@dxos/plugin-attention": "0.6.12-main.568932b",
|
|
70
|
+
"@dxos/log": "0.6.12-main.568932b",
|
|
71
|
+
"@dxos/plugin-client": "0.6.12-main.568932b",
|
|
72
|
+
"@dxos/plugin-metadata": "0.6.12-main.568932b",
|
|
73
|
+
"@dxos/plugin-observability": "0.6.12-main.568932b",
|
|
74
|
+
"@dxos/plugin-graph": "0.6.12-main.568932b",
|
|
75
|
+
"@dxos/plugin-settings": "0.6.12-main.568932b",
|
|
76
|
+
"@dxos/plugin-status-bar": "0.6.12-main.568932b",
|
|
77
|
+
"@dxos/protocols": "0.6.12-main.568932b",
|
|
78
|
+
"@dxos/react-client": "0.6.12-main.568932b",
|
|
79
|
+
"@dxos/react-ui-attention": "0.6.12-main.568932b",
|
|
80
|
+
"@dxos/react-ui-editor": "0.6.12-main.568932b",
|
|
81
|
+
"@dxos/react-ui-syntax-highlighter": "0.6.12-main.568932b",
|
|
82
|
+
"@dxos/shell": "0.6.12-main.568932b",
|
|
83
|
+
"@dxos/util": "0.6.12-main.568932b"
|
|
76
84
|
},
|
|
77
85
|
"devDependencies": {
|
|
78
86
|
"@babel/core": "^7.18.13",
|
|
@@ -82,18 +90,17 @@
|
|
|
82
90
|
"@types/react-dom": "~18.2.0",
|
|
83
91
|
"react": "~18.2.0",
|
|
84
92
|
"react-dom": "~18.2.0",
|
|
85
|
-
"vite": "
|
|
86
|
-
"@dxos/react-ui": "0.6.
|
|
87
|
-
"@dxos/react-ui-theme": "0.6.
|
|
88
|
-
"@dxos/storybook-utils": "0.6.
|
|
93
|
+
"vite": "5.4.7",
|
|
94
|
+
"@dxos/react-ui": "0.6.12-main.568932b",
|
|
95
|
+
"@dxos/react-ui-theme": "0.6.12-main.568932b",
|
|
96
|
+
"@dxos/storybook-utils": "0.6.12-main.568932b"
|
|
89
97
|
},
|
|
90
|
-
"
|
|
91
|
-
"@babel/core": "^7.18.13",
|
|
98
|
+
"peerDependencies": {
|
|
92
99
|
"@phosphor-icons/react": "^2.1.5",
|
|
93
|
-
"react": "
|
|
94
|
-
"react-dom": "
|
|
95
|
-
"@dxos/react-ui": "0.6.
|
|
96
|
-
"@dxos/react-ui-theme": "0.6.
|
|
100
|
+
"react": "~18.2.0",
|
|
101
|
+
"react-dom": "~18.2.0",
|
|
102
|
+
"@dxos/react-ui": "0.6.12-main.568932b",
|
|
103
|
+
"@dxos/react-ui-theme": "0.6.12-main.568932b"
|
|
97
104
|
},
|
|
98
105
|
"publishConfig": {
|
|
99
106
|
"access": "public"
|
package/src/SpacePlugin.tsx
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type IconProps, Plus, SignIn, CardsThree, Warning } from '@phosphor-icons/react';
|
|
6
5
|
import { effect, signal } from '@preact/signals-core';
|
|
7
6
|
import React from 'react';
|
|
8
7
|
|
|
@@ -10,45 +9,45 @@ import {
|
|
|
10
9
|
type IntentDispatcher,
|
|
11
10
|
type IntentPluginProvides,
|
|
12
11
|
LayoutAction,
|
|
13
|
-
Surface,
|
|
14
12
|
type LocationProvides,
|
|
15
13
|
NavigationAction,
|
|
16
14
|
type Plugin,
|
|
17
15
|
type PluginDefinition,
|
|
18
|
-
|
|
16
|
+
Surface,
|
|
19
17
|
firstIdInPart,
|
|
18
|
+
openIds,
|
|
19
|
+
parseGraphPlugin,
|
|
20
20
|
parseIntentPlugin,
|
|
21
|
-
parseNavigationPlugin,
|
|
22
21
|
parseMetadataResolverPlugin,
|
|
22
|
+
parseNavigationPlugin,
|
|
23
23
|
resolvePlugin,
|
|
24
|
-
parseGraphPlugin,
|
|
25
24
|
} from '@dxos/app-framework';
|
|
26
25
|
import { EventSubscriptions, type Trigger, type UnsubscribeCallback } from '@dxos/async';
|
|
27
|
-
import { type Identifiable, isReactiveObject
|
|
26
|
+
import { type EchoReactiveObject, type Identifiable, isReactiveObject } from '@dxos/echo-schema';
|
|
28
27
|
import { LocalStorageStore } from '@dxos/local-storage';
|
|
29
28
|
import { log } from '@dxos/log';
|
|
30
29
|
import { Migrations } from '@dxos/migrations';
|
|
31
30
|
import { type AttentionPluginProvides, parseAttentionPlugin } from '@dxos/plugin-attention';
|
|
32
31
|
import { type ClientPluginProvides, parseClientPlugin } from '@dxos/plugin-client';
|
|
33
|
-
import { createExtension, isGraphNode, memoize,
|
|
32
|
+
import { type Node, createExtension, isGraphNode, memoize, toSignal } from '@dxos/plugin-graph';
|
|
34
33
|
import { ObservabilityAction } from '@dxos/plugin-observability/meta';
|
|
35
34
|
import { type Client, PublicKey } from '@dxos/react-client';
|
|
36
35
|
import {
|
|
36
|
+
Expando,
|
|
37
|
+
Filter,
|
|
37
38
|
type PropertiesTypeProps,
|
|
38
39
|
type Space,
|
|
40
|
+
SpaceState,
|
|
39
41
|
create,
|
|
40
|
-
Expando,
|
|
41
|
-
Filter,
|
|
42
42
|
fullyQualifiedId,
|
|
43
43
|
getSpace,
|
|
44
44
|
getTypename,
|
|
45
45
|
isEchoObject,
|
|
46
46
|
isSpace,
|
|
47
47
|
loadObjectReferences,
|
|
48
|
-
SpaceState,
|
|
49
48
|
} from '@dxos/react-client/echo';
|
|
50
49
|
import { Dialog } from '@dxos/react-ui';
|
|
51
|
-
import { InvitationManager, type InvitationManagerProps, osTranslations
|
|
50
|
+
import { ClipboardProvider, InvitationManager, type InvitationManagerProps, osTranslations } from '@dxos/shell/react';
|
|
52
51
|
import { ComplexMap, nonNullable, reduceGroupBy } from '@dxos/util';
|
|
53
52
|
|
|
54
53
|
import {
|
|
@@ -61,15 +60,17 @@ import {
|
|
|
61
60
|
MissingObject,
|
|
62
61
|
PopoverRenameObject,
|
|
63
62
|
PopoverRenameSpace,
|
|
63
|
+
SaveStatus,
|
|
64
64
|
ShareSpaceButton,
|
|
65
65
|
SmallPresence,
|
|
66
66
|
SmallPresenceLive,
|
|
67
67
|
SpacePresence,
|
|
68
68
|
SpaceSettings,
|
|
69
|
+
SyncStatus,
|
|
69
70
|
} from './components';
|
|
70
71
|
import meta, { SPACE_PLUGIN, SpaceAction } from './meta';
|
|
71
72
|
import translations from './translations';
|
|
72
|
-
import { CollectionType, type
|
|
73
|
+
import { CollectionType, type PluginState, type SpacePluginProvides, type SpaceSettingsProps } from './types';
|
|
73
74
|
import {
|
|
74
75
|
COMPOSER_SPACE_LOCK,
|
|
75
76
|
SHARED,
|
|
@@ -118,7 +119,9 @@ export const SpacePlugin = ({
|
|
|
118
119
|
firstRun,
|
|
119
120
|
onFirstRun,
|
|
120
121
|
}: SpacePluginOptions = {}): PluginDefinition<SpacePluginProvides> => {
|
|
121
|
-
const settings = new LocalStorageStore<SpaceSettingsProps>(SPACE_PLUGIN
|
|
122
|
+
const settings = new LocalStorageStore<SpaceSettingsProps>(SPACE_PLUGIN, {
|
|
123
|
+
onSpaceCreate: 'dxos.org/plugin/markdown/action/create',
|
|
124
|
+
});
|
|
122
125
|
const state = new LocalStorageStore<PluginState>(SPACE_PLUGIN, {
|
|
123
126
|
awaiting: undefined,
|
|
124
127
|
spaceNames: {},
|
|
@@ -340,8 +343,7 @@ export const SpacePlugin = ({
|
|
|
340
343
|
records: {
|
|
341
344
|
[CollectionType.typename]: {
|
|
342
345
|
placeholder: ['unnamed collection label', { ns: SPACE_PLUGIN }],
|
|
343
|
-
icon:
|
|
344
|
-
iconSymbol: 'ph--cards-three--regular',
|
|
346
|
+
icon: 'ph--cards-three--regular',
|
|
345
347
|
// TODO(wittjosiah): Move out of metadata.
|
|
346
348
|
loadReferences: (collection: CollectionType) =>
|
|
347
349
|
loadObjectReferences(collection, (collection) => [
|
|
@@ -362,7 +364,11 @@ export const SpacePlugin = ({
|
|
|
362
364
|
case 'main':
|
|
363
365
|
// TODO(wittjosiah): Need to avoid shotgun parsing space state everywhere.
|
|
364
366
|
return isSpace(primary) && primary.state.get() === SpaceState.SPACE_READY ? (
|
|
365
|
-
<Surface
|
|
367
|
+
<Surface
|
|
368
|
+
data={{ active: primary.properties[CollectionType.typename], id: primary.id }}
|
|
369
|
+
role={role}
|
|
370
|
+
{...rest}
|
|
371
|
+
/>
|
|
366
372
|
) : primary instanceof CollectionType ? (
|
|
367
373
|
{ node: <CollectionMain collection={primary} />, disposition: 'fallback' }
|
|
368
374
|
) : typeof primary === 'string' && primary.length === OBJECT_ID_LENGTH ? (
|
|
@@ -441,6 +447,14 @@ export const SpacePlugin = ({
|
|
|
441
447
|
} else {
|
|
442
448
|
return <MenuFooter object={data.object} />;
|
|
443
449
|
}
|
|
450
|
+
case 'status': {
|
|
451
|
+
return (
|
|
452
|
+
<>
|
|
453
|
+
<SyncStatus />
|
|
454
|
+
<SaveStatus />
|
|
455
|
+
</>
|
|
456
|
+
);
|
|
457
|
+
}
|
|
444
458
|
default:
|
|
445
459
|
return null;
|
|
446
460
|
}
|
|
@@ -540,8 +554,7 @@ export const SpacePlugin = ({
|
|
|
540
554
|
},
|
|
541
555
|
properties: {
|
|
542
556
|
label: ['create space label', { ns: SPACE_PLUGIN }],
|
|
543
|
-
icon:
|
|
544
|
-
iconSymbol: 'ph--plus--regular',
|
|
557
|
+
icon: 'ph--plus--regular',
|
|
545
558
|
disposition: 'toolbar',
|
|
546
559
|
testId: 'spacePlugin.createSpace',
|
|
547
560
|
},
|
|
@@ -561,8 +574,7 @@ export const SpacePlugin = ({
|
|
|
561
574
|
},
|
|
562
575
|
properties: {
|
|
563
576
|
label: ['join space label', { ns: SPACE_PLUGIN }],
|
|
564
|
-
icon:
|
|
565
|
-
iconSymbol: 'ph--sign-in--regular',
|
|
577
|
+
icon: 'ph--sign-in--regular',
|
|
566
578
|
testId: 'spacePlugin.joinSpace',
|
|
567
579
|
},
|
|
568
580
|
},
|
|
@@ -805,6 +817,15 @@ export const SpacePlugin = ({
|
|
|
805
817
|
data: { space, id: space.id, activeParts: { main: [space.id] } },
|
|
806
818
|
|
|
807
819
|
intents: [
|
|
820
|
+
...(settings.values.onSpaceCreate
|
|
821
|
+
? [
|
|
822
|
+
[
|
|
823
|
+
{ action: settings.values.onSpaceCreate, data: { space } },
|
|
824
|
+
{ action: SpaceAction.ADD_OBJECT, data: { target: space } },
|
|
825
|
+
{ action: NavigationAction.EXPOSE },
|
|
826
|
+
],
|
|
827
|
+
]
|
|
828
|
+
: []),
|
|
808
829
|
[
|
|
809
830
|
{
|
|
810
831
|
action: ObservabilityAction.SEND_EVENT,
|
|
@@ -1020,8 +1041,7 @@ export const SpacePlugin = ({
|
|
|
1020
1041
|
title: translations[0]['en-US'][SPACE_PLUGIN]['space limit label'],
|
|
1021
1042
|
description: translations[0]['en-US'][SPACE_PLUGIN]['space limit description'],
|
|
1022
1043
|
duration: 5_000,
|
|
1023
|
-
icon:
|
|
1024
|
-
iconSymbol: 'ph--warning--regular',
|
|
1044
|
+
icon: 'ph--warning--regular',
|
|
1025
1045
|
actionLabel: translations[0]['en-US'][SPACE_PLUGIN]['remove deleted objects label'],
|
|
1026
1046
|
actionAlt: translations[0]['en-US'][SPACE_PLUGIN]['remove deleted objects alt'],
|
|
1027
1047
|
// TODO(wittjosiah): Use OS namespace.
|
|
@@ -1060,7 +1080,7 @@ export const SpacePlugin = ({
|
|
|
1060
1080
|
}
|
|
1061
1081
|
|
|
1062
1082
|
return {
|
|
1063
|
-
data: { id: object
|
|
1083
|
+
data: { id: fullyQualifiedId(object), object, activeParts: { main: [fullyQualifiedId(object)] } },
|
|
1064
1084
|
intents: [
|
|
1065
1085
|
[
|
|
1066
1086
|
{
|
|
@@ -1115,7 +1135,6 @@ export const SpacePlugin = ({
|
|
|
1115
1135
|
activeParts: {
|
|
1116
1136
|
main: deletionData.wasActive,
|
|
1117
1137
|
sidebar: deletionData.wasActive,
|
|
1118
|
-
complementary: deletionData.wasActive,
|
|
1119
1138
|
},
|
|
1120
1139
|
},
|
|
1121
1140
|
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type UnsubscribeCallback } from '@dxos/async';
|
|
8
|
+
import { type Client } from '@dxos/client';
|
|
9
|
+
import { type Space, type SpaceId } from '@dxos/client/echo';
|
|
10
|
+
import { Context } from '@dxos/context';
|
|
11
|
+
import { StatusBar } from '@dxos/plugin-status-bar';
|
|
12
|
+
import { useClient } from '@dxos/react-client';
|
|
13
|
+
import { Icon, useTranslation } from '@dxos/react-ui';
|
|
14
|
+
|
|
15
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
16
|
+
|
|
17
|
+
export const SaveStatus = () => {
|
|
18
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
19
|
+
const client = useClient();
|
|
20
|
+
const [state, setState] = useState<'saved' | 'saving'>('saved');
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
return createClientSaveTracker(client, (state) => {
|
|
23
|
+
setState(state);
|
|
24
|
+
});
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<StatusBar.Item title={state === 'saving' ? t('saving label') : t('saved label')}>
|
|
29
|
+
<Icon icon={state === 'saving' ? 'ph--arrows-clockwise--regular' : 'ph--check-circle--regular'} size={4} />
|
|
30
|
+
</StatusBar.Item>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const createClientSaveTracker = (client: Client, cb: (state: 'saved' | 'saving') => void) => {
|
|
35
|
+
const unsubscribeCallbacks: Record<SpaceId, UnsubscribeCallback> = {};
|
|
36
|
+
const state: Record<SpaceId, 'saved' | 'saving'> = {};
|
|
37
|
+
|
|
38
|
+
const install = (spaces: Space[]) => {
|
|
39
|
+
for (const space of spaces) {
|
|
40
|
+
if (state[space.id]) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
state[space.id] = 'saved';
|
|
45
|
+
unsubscribeCallbacks[space.id] = createSpaceSaveTracker(space, (s) => {
|
|
46
|
+
state[space.id] = s;
|
|
47
|
+
cb(Object.values(state).some((s) => s === 'saving') ? 'saving' : 'saved');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
client.spaces.subscribe((spaces) => {
|
|
52
|
+
install(spaces);
|
|
53
|
+
});
|
|
54
|
+
install(client.spaces.get());
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
for (const unsubscribe of Object.values(unsubscribeCallbacks)) {
|
|
58
|
+
unsubscribe();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const createSpaceSaveTracker = (space: Space, cb: (state: 'saved' | 'saving') => void): UnsubscribeCallback => {
|
|
64
|
+
const ctx = new Context();
|
|
65
|
+
|
|
66
|
+
void space.waitUntilReady().then(() => {
|
|
67
|
+
if (ctx.disposed) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let hasUnsavedChanges = false;
|
|
72
|
+
let lastFlushPromise: Promise<void> | undefined;
|
|
73
|
+
space.crud.saveStateChanged.on(ctx, ({ unsavedDocuments }) => {
|
|
74
|
+
hasUnsavedChanges = unsavedDocuments.length > 0;
|
|
75
|
+
});
|
|
76
|
+
space.crud.saveStateChanged.debounce(500).on(ctx, () => {
|
|
77
|
+
if (hasUnsavedChanges) {
|
|
78
|
+
lastFlushPromise = undefined;
|
|
79
|
+
cb('saving');
|
|
80
|
+
} else {
|
|
81
|
+
const flushPromise = space.crud.flush();
|
|
82
|
+
lastFlushPromise = flushPromise;
|
|
83
|
+
void flushPromise.then(() => {
|
|
84
|
+
if (lastFlushPromise === flushPromise) {
|
|
85
|
+
cb('saved');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return () => {
|
|
93
|
+
void ctx.dispose();
|
|
94
|
+
};
|
|
95
|
+
};
|
|
@@ -6,35 +6,14 @@ import { Command } from '@phosphor-icons/react';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
8
|
import { Surface } from '@dxos/app-framework';
|
|
9
|
-
import { type Action } from '@dxos/plugin-graph';
|
|
10
9
|
import { SpaceState, type Space } from '@dxos/react-client/echo';
|
|
11
|
-
import {
|
|
10
|
+
import { Main, useTranslation } from '@dxos/react-ui';
|
|
12
11
|
import { getSize, mx, topbarBlockPaddingStart } from '@dxos/react-ui-theme';
|
|
13
12
|
import { ClipboardProvider } from '@dxos/shell/react';
|
|
14
13
|
|
|
15
14
|
import { SpaceMembersSection } from './SpaceMembersSection';
|
|
16
15
|
import { SPACE_PLUGIN } from '../../meta';
|
|
17
16
|
|
|
18
|
-
const _InFlowSpaceActions = ({ actionsMap }: { actionsMap: Record<string, Action> }) => {
|
|
19
|
-
const { t } = useTranslation(SPACE_PLUGIN);
|
|
20
|
-
return (
|
|
21
|
-
<section className='mbe-4 col-start-2 col-end-4 md:col-end-7 grid gap-2 auto-rows-min grid-cols-[repeat(auto-fill,minmax(8rem,1fr))]'>
|
|
22
|
-
{Object.entries(actionsMap)
|
|
23
|
-
.filter(([_, { properties }]) => properties?.mainAreaDisposition === 'in-flow')
|
|
24
|
-
.map(([actionId, { data: invoke, properties }]) => {
|
|
25
|
-
const Icon = properties?.icon;
|
|
26
|
-
const label = properties?.label;
|
|
27
|
-
return (
|
|
28
|
-
<Button key={actionId} classNames='block text-center plb-2 font-normal'>
|
|
29
|
-
{Icon && <Icon size={5} className='mli-auto' />}
|
|
30
|
-
<p>{toLocalizedString(label, t)}</p>
|
|
31
|
-
</Button>
|
|
32
|
-
);
|
|
33
|
-
})}
|
|
34
|
-
</section>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
17
|
const KeyShortcuts = () => {
|
|
39
18
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
40
19
|
return (
|
|
@@ -110,7 +110,7 @@ export type MemberPresenceProps = ThemedClassName<{
|
|
|
110
110
|
|
|
111
111
|
export const FullPresence = (props: MemberPresenceProps) => {
|
|
112
112
|
const { size = 9, onMemberClick } = props;
|
|
113
|
-
const members = useDefaultValue(props.members, []);
|
|
113
|
+
const members = useDefaultValue(props.members, () => []);
|
|
114
114
|
|
|
115
115
|
if (members.length === 0) {
|
|
116
116
|
return null;
|
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
7
|
+
import { useIntentDispatcher, useResolvePlugins } from '@dxos/app-framework';
|
|
8
8
|
import { SettingsValue } from '@dxos/plugin-settings';
|
|
9
|
-
import { Input, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
import { Input, Select, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
|
|
11
11
|
import { SpaceAction, SPACE_PLUGIN } from '../meta';
|
|
12
|
-
import { type SpaceSettingsProps } from '../types';
|
|
12
|
+
import { parseSpaceInitPlugin, type SpaceSettingsProps } from '../types';
|
|
13
13
|
|
|
14
14
|
export const SpaceSettings = ({ settings }: { settings: SpaceSettingsProps }) => {
|
|
15
15
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
16
16
|
const dispatch = useIntentDispatcher();
|
|
17
|
+
const plugins = useResolvePlugins(parseSpaceInitPlugin);
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
20
|
<>
|
|
@@ -29,6 +30,34 @@ export const SpaceSettings = ({ settings }: { settings: SpaceSettingsProps }) =>
|
|
|
29
30
|
}
|
|
30
31
|
/>
|
|
31
32
|
</SettingsValue>
|
|
33
|
+
|
|
34
|
+
<SettingsValue label={t('default on space create label')}>
|
|
35
|
+
<Select.Root
|
|
36
|
+
value={settings.onSpaceCreate}
|
|
37
|
+
onValueChange={(value) => {
|
|
38
|
+
settings.onSpaceCreate = value;
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<Select.TriggerButton />
|
|
42
|
+
<Select.Portal>
|
|
43
|
+
<Select.Content>
|
|
44
|
+
<Select.Viewport>
|
|
45
|
+
{plugins.map(
|
|
46
|
+
({
|
|
47
|
+
provides: {
|
|
48
|
+
space: { onSpaceCreate },
|
|
49
|
+
},
|
|
50
|
+
}) => (
|
|
51
|
+
<Select.Option key={onSpaceCreate.action} value={onSpaceCreate.action}>
|
|
52
|
+
{toLocalizedString(onSpaceCreate.label, t)}
|
|
53
|
+
</Select.Option>
|
|
54
|
+
),
|
|
55
|
+
)}
|
|
56
|
+
</Select.Viewport>
|
|
57
|
+
</Select.Content>
|
|
58
|
+
</Select.Portal>
|
|
59
|
+
</Select.Root>
|
|
60
|
+
</SettingsValue>
|
|
32
61
|
</>
|
|
33
62
|
);
|
|
34
63
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
|
|
9
|
+
import { SpaceId } from '@dxos/keys';
|
|
10
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
11
|
+
|
|
12
|
+
import { SyncStatusDetail, SyncStatusIndicator } from './SyncStatus';
|
|
13
|
+
import { getSyncSummary, type SpaceSyncStateMap } from './types';
|
|
14
|
+
import translations from '../../translations';
|
|
15
|
+
|
|
16
|
+
const Story = (props: any) => {
|
|
17
|
+
return (
|
|
18
|
+
<div className='flex flex-col-reverse p-4 '>
|
|
19
|
+
<SyncStatusIndicator {...props} />
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default {
|
|
25
|
+
title: 'plugin-space/SyncStatusIndicator',
|
|
26
|
+
decorators: [withTheme, withLayout({ fullscreen: true })],
|
|
27
|
+
component: SyncStatusIndicator,
|
|
28
|
+
parameters: { translations },
|
|
29
|
+
render: Story,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const random = ({ min, max }: { min: number; max: number }) => min + Math.floor(Math.random() * (max - min));
|
|
33
|
+
|
|
34
|
+
const state: SpaceSyncStateMap = Array.from({ length: 5 }).reduce<SpaceSyncStateMap>((map) => {
|
|
35
|
+
const total = random({ min: 10, max: 500 });
|
|
36
|
+
const haveLocal = random({ min: 0, max: total });
|
|
37
|
+
const haveRemote = random({ min: 0, max: total });
|
|
38
|
+
map[SpaceId.random()] = {
|
|
39
|
+
localDocumentCount: haveLocal,
|
|
40
|
+
remoteDocumentCount: haveRemote,
|
|
41
|
+
missingOnLocal: total - haveLocal,
|
|
42
|
+
missingOnRemote: total - haveRemote,
|
|
43
|
+
differentDocuments: 0,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return map;
|
|
47
|
+
}, {});
|
|
48
|
+
|
|
49
|
+
export const Default = {
|
|
50
|
+
args: {
|
|
51
|
+
state,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Detail = {
|
|
56
|
+
render: SyncStatusDetail,
|
|
57
|
+
args: {
|
|
58
|
+
state,
|
|
59
|
+
summary: getSyncSummary(state),
|
|
60
|
+
classNames: 'm-2 w-[200px] border border-separator rounded-md',
|
|
61
|
+
},
|
|
62
|
+
};
|