@dxos/plugin-space 0.7.4 → 0.7.5-main.9cb18ac
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-54VE4GTA.mjs +315 -0
- package/dist/lib/browser/chunk-54VE4GTA.mjs.map +7 -0
- package/dist/lib/browser/chunk-73BCBSLP.mjs +15 -0
- package/dist/lib/browser/chunk-73BCBSLP.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +928 -962
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -5
- package/dist/lib/browser/types/index.mjs +8 -1
- package/dist/lib/node/chunk-46S3JOES.cjs +39 -0
- package/dist/lib/node/chunk-46S3JOES.cjs.map +7 -0
- package/dist/lib/node/chunk-YF2AQ7KP.cjs +343 -0
- package/dist/lib/node/chunk-YF2AQ7KP.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1053 -1086
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.cjs +5 -9
- package/dist/lib/node/meta.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +19 -12
- package/dist/lib/node/types/index.cjs.map +2 -2
- package/dist/lib/node-esm/chunk-2MNFEB23.mjs +17 -0
- package/dist/lib/node-esm/chunk-2MNFEB23.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CDZETPO7.mjs +316 -0
- package/dist/lib/node-esm/chunk-CDZETPO7.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +928 -962
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/meta.mjs +1 -5
- package/dist/lib/node-esm/types/index.mjs +8 -1
- package/dist/types/src/SpacePlugin.d.ts +2 -2
- package/dist/types/src/SpacePlugin.d.ts.map +1 -1
- package/dist/types/src/components/AwaitingObject.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +4 -2
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +3 -3
- 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/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/meta.d.ts +0 -23
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -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 +234 -4
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +3 -3
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +39 -38
- package/src/SpacePlugin.tsx +477 -602
- package/src/components/AwaitingObject.tsx +19 -17
- package/src/components/CreateDialog/CreateObjectDialog.tsx +33 -22
- package/src/components/CreateDialog/CreateObjectPanel.tsx +7 -7
- 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 +5 -11
- package/src/components/SpacePresence.stories.tsx +25 -17
- package/src/components/SpacePresence.tsx +36 -16
- 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/hooks/index.ts +5 -0
- package/src/hooks/usePath.ts +44 -0
- package/src/meta.ts +0 -26
- package/src/translations.ts +3 -2
- package/src/types/collection.ts +3 -3
- package/src/types/thread.ts +6 -6
- package/src/types/types.ts +182 -13
- package/src/util.tsx +59 -52
- 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/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-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/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
|
@@ -3,15 +3,22 @@
|
|
|
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 {
|
|
9
|
+
useResolvePlugin,
|
|
10
|
+
parseNavigationPlugin,
|
|
11
|
+
NavigationAction,
|
|
12
|
+
useIntentDispatcher,
|
|
13
|
+
createIntent,
|
|
14
|
+
} from '@dxos/app-framework';
|
|
9
15
|
import { useClient } from '@dxos/react-client';
|
|
10
16
|
import { Filter, fullyQualifiedId, useQuery } from '@dxos/react-client/echo';
|
|
11
17
|
import { Button, Toast, useTranslation } from '@dxos/react-ui';
|
|
12
18
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
13
19
|
|
|
14
|
-
import {
|
|
20
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
21
|
+
import { SpaceAction } from '../types';
|
|
15
22
|
|
|
16
23
|
const WAIT_FOR_OBJECT_TIMEOUT = 180e3; // 3 minutes
|
|
17
24
|
const TOAST_TIMEOUT = 240e3; // 4 minutes
|
|
@@ -21,7 +28,7 @@ export const AwaitingObject = ({ id }: { id: string }) => {
|
|
|
21
28
|
const [waiting, setWaiting] = useState(true);
|
|
22
29
|
const [found, setFound] = useState(false);
|
|
23
30
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
24
|
-
const
|
|
31
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
25
32
|
const navigationPlugin = useResolvePlugin(parseNavigationPlugin);
|
|
26
33
|
|
|
27
34
|
const client = useClient();
|
|
@@ -47,22 +54,17 @@ export const AwaitingObject = ({ id }: { id: string }) => {
|
|
|
47
54
|
setOpen(false);
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
|
-
}, [id, objects,
|
|
57
|
+
}, [id, objects, navigationPlugin]);
|
|
51
58
|
|
|
52
|
-
const handleClose =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
data: { id: undefined },
|
|
57
|
-
});
|
|
59
|
+
const handleClose = useCallback(
|
|
60
|
+
async () => dispatch(createIntent(SpaceAction.WaitForObject, { id: undefined })),
|
|
61
|
+
[dispatch],
|
|
62
|
+
);
|
|
58
63
|
|
|
59
|
-
const handleNavigate = () => {
|
|
60
|
-
void
|
|
61
|
-
action: NavigationAction.OPEN,
|
|
62
|
-
data: { activeParts: { main: [id] } },
|
|
63
|
-
});
|
|
64
|
+
const handleNavigate = useCallback(() => {
|
|
65
|
+
void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [id] } }));
|
|
64
66
|
void handleClose();
|
|
65
|
-
};
|
|
67
|
+
}, [id, handleClose, dispatch]);
|
|
66
68
|
|
|
67
69
|
return (
|
|
68
70
|
<Toast.Root open={open} duration={TOAST_TIMEOUT} onOpenChange={setOpen}>
|
|
@@ -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 { type MetadataResolver, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { chain, createIntent, type MetadataResolver, 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
27
|
resolve?: MetadataResolver;
|
|
18
|
-
|
|
28
|
+
shouldNavigate?: (object: ReactiveObject<any>) => boolean;
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
export const CreateObjectDialog = ({
|
|
@@ -23,14 +33,14 @@ 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 ({
|
|
@@ -38,13 +48,15 @@ export const CreateObjectDialog = ({
|
|
|
38
48
|
target: _target,
|
|
39
49
|
name,
|
|
40
50
|
}: {
|
|
41
|
-
schema:
|
|
51
|
+
schema: TypedObject;
|
|
42
52
|
target: CreateObjectPanelProps['target'];
|
|
43
53
|
name?: string;
|
|
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({ name, 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>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { useCallback, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { type MetadataResolver } from '@dxos/app-framework';
|
|
8
|
-
import { type
|
|
8
|
+
import { type TypedObject, getObjectAnnotation, S } from '@dxos/echo-schema';
|
|
9
9
|
import { type SpaceId, type Space, isSpace } from '@dxos/react-client/echo';
|
|
10
10
|
import { Icon, IconButton, Input, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
11
11
|
import { Form, InputHeader } from '@dxos/react-ui-form';
|
|
@@ -17,7 +17,7 @@ import { type CollectionType } from '../../types';
|
|
|
17
17
|
import { getSpaceDisplayName } from '../../util';
|
|
18
18
|
|
|
19
19
|
export type CreateObjectPanelProps = {
|
|
20
|
-
schemas:
|
|
20
|
+
schemas: TypedObject[];
|
|
21
21
|
spaces: Space[];
|
|
22
22
|
typename?: string;
|
|
23
23
|
target?: Space | CollectionType;
|
|
@@ -25,7 +25,7 @@ export type CreateObjectPanelProps = {
|
|
|
25
25
|
defaultSpaceId?: SpaceId;
|
|
26
26
|
resolve?: MetadataResolver;
|
|
27
27
|
onCreateObject?: (params: {
|
|
28
|
-
schema:
|
|
28
|
+
schema: TypedObject;
|
|
29
29
|
target: Space | CollectionType;
|
|
30
30
|
name?: string;
|
|
31
31
|
}) => MaybePromise<void>;
|
|
@@ -63,7 +63,7 @@ export const CreateObjectPanel = ({
|
|
|
63
63
|
|
|
64
64
|
// TODO(wittjosiah): All of these inputs should be rolled into a `Form` once it supports the necessary variants.
|
|
65
65
|
const schemaInput = (
|
|
66
|
-
<SearchList.Root label={t('schema input label')} classNames='flex flex-col grow overflow-hidden
|
|
66
|
+
<SearchList.Root label={t('schema input label')} classNames='flex flex-col grow overflow-hidden'>
|
|
67
67
|
<SearchList.Input
|
|
68
68
|
autoFocus
|
|
69
69
|
data-testid='create-object-form.schema-input'
|
|
@@ -89,7 +89,7 @@ export const CreateObjectPanel = ({
|
|
|
89
89
|
);
|
|
90
90
|
|
|
91
91
|
const spaceInput = (
|
|
92
|
-
<SearchList.Root label={t('space input label')} classNames='flex flex-col grow overflow-hidden
|
|
92
|
+
<SearchList.Root label={t('space input label')} classNames='flex flex-col grow overflow-hidden'>
|
|
93
93
|
<SearchList.Input
|
|
94
94
|
autoFocus
|
|
95
95
|
data-testid='create-object-form.space-input'
|
|
@@ -126,7 +126,7 @@ export const CreateObjectPanel = ({
|
|
|
126
126
|
return (
|
|
127
127
|
<div role='form' className='flex flex-col gap-2'>
|
|
128
128
|
{target && (
|
|
129
|
-
<div role='none'
|
|
129
|
+
<div role='none'>
|
|
130
130
|
<Input.Root>
|
|
131
131
|
<InputHeader>
|
|
132
132
|
<Input.Label>
|
|
@@ -148,7 +148,7 @@ export const CreateObjectPanel = ({
|
|
|
148
148
|
</div>
|
|
149
149
|
)}
|
|
150
150
|
{schema && (
|
|
151
|
-
<div role='none'
|
|
151
|
+
<div role='none'>
|
|
152
152
|
<Input.Root>
|
|
153
153
|
<InputHeader>
|
|
154
154
|
<Input.Label>{t('creating object type label')}</Input.Label>
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useRef } from 'react';
|
|
6
6
|
|
|
7
|
-
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
7
|
+
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { type S } from '@dxos/echo-schema';
|
|
9
9
|
import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { Form } from '@dxos/react-ui-form';
|
|
11
11
|
|
|
12
|
-
import { SPACE_PLUGIN
|
|
13
|
-
import { SpaceForm } from '../../types';
|
|
12
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
13
|
+
import { SpaceAction, SpaceForm } from '../../types';
|
|
14
|
+
|
|
15
|
+
export const CREATE_SPACE_DIALOG = `${SPACE_PLUGIN}/CreateSpaceDialog`;
|
|
14
16
|
|
|
15
17
|
type FormValues = S.Schema.Type<typeof SpaceForm>;
|
|
16
18
|
const initialValues: FormValues = { edgeReplication: true };
|
|
@@ -18,20 +20,14 @@ const initialValues: FormValues = { edgeReplication: true };
|
|
|
18
20
|
export const CreateSpaceDialog = () => {
|
|
19
21
|
const closeRef = useRef<HTMLButtonElement | null>(null);
|
|
20
22
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
21
|
-
const dispatch = useIntentDispatcher();
|
|
23
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
22
24
|
|
|
23
25
|
const handleCreateSpace = useCallback(
|
|
24
26
|
async (data: FormValues) => {
|
|
25
|
-
const result = await dispatch(
|
|
26
|
-
|
|
27
|
-
data,
|
|
28
|
-
});
|
|
29
|
-
const target = result?.data.space;
|
|
27
|
+
const result = await dispatch(createIntent(SpaceAction.Create, data));
|
|
28
|
+
const target = result.data?.space;
|
|
30
29
|
if (target) {
|
|
31
|
-
await dispatch({
|
|
32
|
-
action: SpaceAction.OPEN_CREATE_OBJECT,
|
|
33
|
-
data: { target },
|
|
34
|
-
});
|
|
30
|
+
await dispatch(createIntent(SpaceAction.OpenCreateObject, { target }));
|
|
35
31
|
}
|
|
36
32
|
},
|
|
37
33
|
[dispatch],
|
|
@@ -41,7 +37,7 @@ export const CreateSpaceDialog = () => {
|
|
|
41
37
|
// TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
|
|
42
38
|
// Consider factoring it out to the tabs package.
|
|
43
39
|
<Dialog.Content classNames='p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden'>
|
|
44
|
-
<div role='none' className='flex justify-between pbs-
|
|
40
|
+
<div role='none' className='flex justify-between pbs-2 pis-2 pie-2 @md:pbs-4 @md:pis-4 @md:pie-4'>
|
|
45
41
|
<Dialog.Title>{t('create space dialog title')}</Dialog.Title>
|
|
46
42
|
<Dialog.Close asChild>
|
|
47
43
|
<Button ref={closeRef} density='fine' variant='ghost' autoFocus>
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback } from 'react';
|
|
6
6
|
|
|
7
|
-
import { LayoutAction, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
7
|
+
import { createIntent, LayoutAction, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { useGraph } from '@dxos/plugin-graph';
|
|
9
|
-
import { ObservabilityAction } from '@dxos/plugin-observability/
|
|
9
|
+
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
10
10
|
import { useSpaces } from '@dxos/react-client/echo';
|
|
11
11
|
import { type InvitationResult } from '@dxos/react-client/invitations';
|
|
12
12
|
import { Dialog, useTranslation } from '@dxos/react-ui';
|
|
@@ -14,13 +14,15 @@ import { JoinPanel, type JoinPanelProps } from '@dxos/shell/react';
|
|
|
14
14
|
|
|
15
15
|
import { SPACE_PLUGIN } from '../meta';
|
|
16
16
|
|
|
17
|
+
export const JOIN_DIALOG = `${SPACE_PLUGIN}/JoinDialog`;
|
|
18
|
+
|
|
17
19
|
export type JoinDialogProps = JoinPanelProps & {
|
|
18
20
|
navigableCollections?: boolean;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialogProps) => {
|
|
22
24
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
23
|
-
const dispatch = useIntentDispatcher();
|
|
25
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
24
26
|
const spaces = useSpaces();
|
|
25
27
|
const { graph } = useGraph();
|
|
26
28
|
|
|
@@ -28,9 +30,8 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
|
|
|
28
30
|
async (result: InvitationResult | null) => {
|
|
29
31
|
if (result?.spaceKey) {
|
|
30
32
|
await Promise.all([
|
|
31
|
-
dispatch(
|
|
32
|
-
|
|
33
|
-
data: {
|
|
33
|
+
dispatch(
|
|
34
|
+
createIntent(LayoutAction.SetLayout, {
|
|
34
35
|
element: 'toast',
|
|
35
36
|
subject: {
|
|
36
37
|
id: `${SPACE_PLUGIN}/join-success`,
|
|
@@ -38,15 +39,14 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
|
|
|
38
39
|
title: t('join success label'),
|
|
39
40
|
closeLabel: t('dismiss label'),
|
|
40
41
|
},
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
dispatch(
|
|
44
|
-
|
|
45
|
-
data: {
|
|
42
|
+
}),
|
|
43
|
+
),
|
|
44
|
+
dispatch(
|
|
45
|
+
createIntent(LayoutAction.SetLayout, {
|
|
46
46
|
element: 'dialog',
|
|
47
47
|
state: false,
|
|
48
|
-
},
|
|
49
|
-
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
50
|
]);
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -60,33 +60,17 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
|
|
|
60
60
|
// If the target has not yet replicated, this will trigger a loading toast.
|
|
61
61
|
await graph.waitForPath({ target }).catch(() => {});
|
|
62
62
|
await Promise.all([
|
|
63
|
-
dispatch({
|
|
64
|
-
|
|
65
|
-
data: {
|
|
66
|
-
activeParts: { main: [target] },
|
|
67
|
-
},
|
|
68
|
-
}),
|
|
69
|
-
dispatch({
|
|
70
|
-
action: NavigationAction.EXPOSE,
|
|
71
|
-
data: {
|
|
72
|
-
id: target,
|
|
73
|
-
},
|
|
74
|
-
}),
|
|
63
|
+
dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [target] } })),
|
|
64
|
+
dispatch(createIntent(NavigationAction.Expose, { id: target })),
|
|
75
65
|
]);
|
|
76
66
|
}
|
|
77
67
|
|
|
78
68
|
await onDone?.(result);
|
|
79
69
|
|
|
80
70
|
if (space) {
|
|
81
|
-
await dispatch(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
name: 'space.join',
|
|
85
|
-
properties: {
|
|
86
|
-
spaceId: space.id,
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
});
|
|
71
|
+
await dispatch(
|
|
72
|
+
createIntent(ObservabilityAction.SendEvent, { name: 'space.join', properties: { spaceId: space.id } }),
|
|
73
|
+
);
|
|
90
74
|
}
|
|
91
75
|
},
|
|
92
76
|
[dispatch, spaces],
|
|
@@ -10,6 +10,8 @@ import { Button, Input, Popover, useTranslation } from '@dxos/react-ui';
|
|
|
10
10
|
|
|
11
11
|
import { SPACE_PLUGIN } from '../meta';
|
|
12
12
|
|
|
13
|
+
export const POPOVER_RENAME_OBJECT = `${SPACE_PLUGIN}/PopoverRenameObject`;
|
|
14
|
+
|
|
13
15
|
export const PopoverRenameObject = ({ object: obj }: { object: ReactiveObject<any> }) => {
|
|
14
16
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
15
17
|
const doneButton = useRef<HTMLButtonElement>(null);
|
|
@@ -9,6 +9,8 @@ import { Button, Input, Popover, useTranslation } from '@dxos/react-ui';
|
|
|
9
9
|
|
|
10
10
|
import { SPACE_PLUGIN } from '../meta';
|
|
11
11
|
|
|
12
|
+
export const POPOVER_RENAME_SPACE = `${SPACE_PLUGIN}/PopoverRenameSpace`;
|
|
13
|
+
|
|
12
14
|
export const PopoverRenameSpace = ({ space }: { space: Space }) => {
|
|
13
15
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
14
16
|
const doneButton = useRef<HTMLButtonElement>(null);
|
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
7
|
+
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { type Space } from '@dxos/react-client/echo';
|
|
9
9
|
import { IconButton, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
|
|
11
|
-
import { SPACE_PLUGIN
|
|
11
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
12
|
+
import { SpaceAction } from '../types';
|
|
12
13
|
|
|
13
14
|
export const ShareSpaceButton = ({ space }: { space: Space }) => {
|
|
14
|
-
const dispatch = useIntentDispatcher();
|
|
15
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
15
16
|
|
|
16
|
-
return <ShareSpaceButtonImpl onClick={() => dispatch(
|
|
17
|
+
return <ShareSpaceButtonImpl onClick={() => dispatch(createIntent(SpaceAction.Share, { space }))} />;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
// TODO(wittjosiah): Better way to name pure/impure components?
|
|
@@ -4,29 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
7
|
+
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { Input, useTranslation } from '@dxos/react-ui';
|
|
9
9
|
import { DeprecatedFormInput } from '@dxos/react-ui-form';
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { type SpaceSettingsProps } from '../types';
|
|
11
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
12
|
+
import { SpaceAction, type SpaceSettingsProps } from '../types';
|
|
13
13
|
|
|
14
14
|
export const SpacePluginSettings = ({ settings }: { settings: SpaceSettingsProps }) => {
|
|
15
15
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
16
|
-
const dispatch = useIntentDispatcher();
|
|
16
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<>
|
|
20
20
|
<DeprecatedFormInput label={t('show hidden spaces label')}>
|
|
21
21
|
<Input.Switch
|
|
22
22
|
checked={settings.showHidden}
|
|
23
|
-
onCheckedChange={(checked) =>
|
|
24
|
-
dispatch({
|
|
25
|
-
plugin: SPACE_PLUGIN,
|
|
26
|
-
action: SpaceAction.TOGGLE_HIDDEN,
|
|
27
|
-
data: { state: !!checked },
|
|
28
|
-
})
|
|
29
|
-
}
|
|
23
|
+
onCheckedChange={(checked) => dispatch(createIntent(SpaceAction.ToggleHidden, { state: !!checked }))}
|
|
30
24
|
/>
|
|
31
25
|
</DeprecatedFormInput>
|
|
32
26
|
</>
|
|
@@ -61,30 +61,38 @@ export const Full = (props: MemberPresenceProps) => {
|
|
|
61
61
|
);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
export const Small = (
|
|
65
|
-
const p: MemberPresenceProps = {
|
|
66
|
-
...props,
|
|
67
|
-
};
|
|
68
|
-
|
|
64
|
+
export const Small = () => {
|
|
69
65
|
return (
|
|
70
66
|
<div className='p-4'>
|
|
71
|
-
<div className='p-3'>
|
|
72
|
-
<SmallPresence count={0}
|
|
67
|
+
<div className='flex gap-3 p-3'>
|
|
68
|
+
<SmallPresence count={0} />
|
|
69
|
+
<SmallPresence count={0} attended />
|
|
70
|
+
<SmallPresence count={0} containsAttended />
|
|
73
71
|
</div>
|
|
74
|
-
<div className='p-3'>
|
|
75
|
-
<SmallPresence count={1}
|
|
72
|
+
<div className='flex gap-3 p-3'>
|
|
73
|
+
<SmallPresence count={1} />
|
|
74
|
+
<SmallPresence count={1} attended />
|
|
75
|
+
<SmallPresence count={1} containsAttended />
|
|
76
76
|
</div>
|
|
77
|
-
<div className='p-3'>
|
|
78
|
-
<SmallPresence count={2}
|
|
77
|
+
<div className='flex gap-3 p-3'>
|
|
78
|
+
<SmallPresence count={2} />
|
|
79
|
+
<SmallPresence count={2} attended />
|
|
80
|
+
<SmallPresence count={2} containsAttended />
|
|
79
81
|
</div>
|
|
80
|
-
<div className='p-3'>
|
|
81
|
-
<SmallPresence count={3}
|
|
82
|
+
<div className='flex gap-3 p-3'>
|
|
83
|
+
<SmallPresence count={3} />
|
|
84
|
+
<SmallPresence count={3} attended />
|
|
85
|
+
<SmallPresence count={3} containsAttended />
|
|
82
86
|
</div>
|
|
83
|
-
<div className='p-3'>
|
|
84
|
-
<SmallPresence count={4}
|
|
87
|
+
<div className='flex gap-3 p-3'>
|
|
88
|
+
<SmallPresence count={4} />
|
|
89
|
+
<SmallPresence count={4} attended />
|
|
90
|
+
<SmallPresence count={4} containsAttended />
|
|
85
91
|
</div>
|
|
86
|
-
<div className='p-3'>
|
|
87
|
-
<SmallPresence count={5}
|
|
92
|
+
<div className='flex gap-3 p-3'>
|
|
93
|
+
<SmallPresence count={5} />
|
|
94
|
+
<SmallPresence count={5} attended />
|
|
95
|
+
<SmallPresence count={5} containsAttended />
|
|
88
96
|
</div>
|
|
89
97
|
</div>
|
|
90
98
|
);
|
|
@@ -7,6 +7,7 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|
|
7
7
|
import { usePlugin } from '@dxos/app-framework';
|
|
8
8
|
import { generateName } from '@dxos/display-name';
|
|
9
9
|
import { type Expando } from '@dxos/echo-schema';
|
|
10
|
+
import { useGraph } from '@dxos/plugin-graph';
|
|
10
11
|
import { PublicKey, useClient } from '@dxos/react-client';
|
|
11
12
|
import { getSpace, useMembers, type SpaceMember, fullyQualifiedId } from '@dxos/react-client/echo';
|
|
12
13
|
import { type Identity, useIdentity } from '@dxos/react-client/halo';
|
|
@@ -22,9 +23,10 @@ import {
|
|
|
22
23
|
ListItem,
|
|
23
24
|
useDefaultValue,
|
|
24
25
|
} from '@dxos/react-ui';
|
|
25
|
-
import { AttentionGlyph, useAttention } from '@dxos/react-ui-attention';
|
|
26
|
+
import { AttentionGlyph, useAttended, useAttention, type AttentionGlyphProps } from '@dxos/react-ui-attention';
|
|
26
27
|
import { ComplexMap, keyToFallback } from '@dxos/util';
|
|
27
28
|
|
|
29
|
+
import { usePath } from '../hooks';
|
|
28
30
|
import { SPACE_PLUGIN } from '../meta';
|
|
29
31
|
import type { ObjectViewerProps, SpacePluginProvides } from '../types';
|
|
30
32
|
|
|
@@ -194,16 +196,30 @@ const PrensenceAvatar = ({ identity, showName, match, group, index, onClick }: P
|
|
|
194
196
|
);
|
|
195
197
|
};
|
|
196
198
|
|
|
197
|
-
export
|
|
198
|
-
id,
|
|
199
|
-
viewers,
|
|
200
|
-
}: {
|
|
199
|
+
export type SmallPresenceLiveProps = {
|
|
201
200
|
id?: string;
|
|
201
|
+
open?: boolean;
|
|
202
202
|
viewers?: ComplexMap<PublicKey, ObjectViewerProps>;
|
|
203
|
-
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const SmallPresenceLive = ({ id, open, viewers }: SmallPresenceLiveProps) => {
|
|
206
|
+
const { hasAttention, isAncestor, isRelated } = useAttention(id);
|
|
207
|
+
const isAttended = hasAttention || isAncestor || isRelated;
|
|
208
|
+
|
|
209
|
+
// TODO(wittjosiah): If the attended node is deep in the graph and the graph is not fully loaded
|
|
210
|
+
// this will result in an empty path until the graph is connected.
|
|
211
|
+
// TODO(wittjosiah): Consider using this indicator for all open nodes instead of just attended.
|
|
212
|
+
const { graph } = useGraph();
|
|
213
|
+
const attended = useAttended();
|
|
214
|
+
const startOfAttention = attended.at(-1);
|
|
215
|
+
const path = usePath(graph, startOfAttention);
|
|
216
|
+
const containsAttended = !open && !isAttended && id && path ? path.includes(id) : false;
|
|
217
|
+
|
|
204
218
|
const getActiveViewers = (viewers: ComplexMap<PublicKey, ObjectViewerProps>): ObjectViewerProps[] => {
|
|
205
219
|
const moment = Date.now();
|
|
206
|
-
return Array.from(viewers.values()).filter(
|
|
220
|
+
return Array.from<ObjectViewerProps>(viewers.values()).filter(
|
|
221
|
+
(viewer) => moment - viewer.lastSeen < ACTIVITY_DURATION,
|
|
222
|
+
);
|
|
207
223
|
};
|
|
208
224
|
|
|
209
225
|
const [activeViewers, setActiveViewers] = useState(viewers ? getActiveViewers(viewers) : []);
|
|
@@ -218,24 +234,28 @@ export const SmallPresenceLive = ({
|
|
|
218
234
|
}
|
|
219
235
|
}, [viewers]);
|
|
220
236
|
|
|
221
|
-
return <SmallPresence
|
|
237
|
+
return <SmallPresence count={activeViewers.length} attended={isAttended} containsAttended={containsAttended} />;
|
|
222
238
|
};
|
|
223
239
|
|
|
224
|
-
export
|
|
240
|
+
export type SmallPresenceProps = {
|
|
241
|
+
count?: number;
|
|
242
|
+
} & Pick<AttentionGlyphProps, 'attended' | 'containsAttended'>;
|
|
243
|
+
|
|
244
|
+
export const SmallPresence = ({ count = 0, attended, containsAttended }: SmallPresenceProps) => {
|
|
225
245
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
226
|
-
const { hasAttention, isAncestor, isRelated } = useAttention(id);
|
|
227
|
-
const attention = hasAttention || isAncestor || isRelated;
|
|
228
246
|
|
|
229
247
|
return (
|
|
230
248
|
<Tooltip.Root>
|
|
231
249
|
<Tooltip.Trigger asChild>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
250
|
+
<AttentionGlyph
|
|
251
|
+
attended={attended}
|
|
252
|
+
containsAttended={containsAttended}
|
|
253
|
+
presence={count > 1 ? 'many' : count === 1 ? 'one' : 'none'}
|
|
254
|
+
classNames='self-center mie-1'
|
|
255
|
+
/>
|
|
236
256
|
</Tooltip.Trigger>
|
|
237
257
|
<Tooltip.Portal>
|
|
238
|
-
<Tooltip.Content side='bottom'
|
|
258
|
+
<Tooltip.Content side='bottom'>
|
|
239
259
|
<span>{t('presence label', { count })}</span>
|
|
240
260
|
<Tooltip.Arrow />
|
|
241
261
|
</Tooltip.Content>
|
|
@@ -7,7 +7,7 @@ import '@dxos-theme';
|
|
|
7
7
|
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
8
|
import React from 'react';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
11
11
|
import { Dialog } from '@dxos/react-ui';
|
|
12
12
|
import { osTranslations } from '@dxos/shell/react';
|
|
13
13
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
@@ -16,8 +16,7 @@ import { SpaceSettingsDialog, type SpaceSettingsDialogProps } from './SpaceSetti
|
|
|
16
16
|
import translations from '../../translations';
|
|
17
17
|
|
|
18
18
|
const Story = (args: Partial<SpaceSettingsDialogProps>) => {
|
|
19
|
-
const { space } =
|
|
20
|
-
|
|
19
|
+
const { space } = useClientProvider();
|
|
21
20
|
return (
|
|
22
21
|
<Dialog.Root open>
|
|
23
22
|
<Dialog.Overlay blockAlign='start'>
|