@dxos/shell 0.6.14-main.2b6a0f3 → 0.6.14-main.69511f5
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/bundle/shell.mjs +15116 -11401
- package/dist/bundle/shell.mjs.map +1 -1
- package/dist/bundle/shell.umd.js +134 -89
- package/dist/bundle/shell.umd.js.map +1 -1
- package/dist/bundle/style.css +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react.mjs +465 -364
- package/dist/lib/browser/react.mjs.map +4 -4
- package/dist/lib/browser/testing/index.mjs +1 -39
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node/chunk-Q7SFCCGT.cjs +33 -0
- package/dist/lib/node/chunk-Q7SFCCGT.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node/react.cjs +4763 -0
- package/dist/lib/node/react.cjs.map +7 -0
- package/dist/lib/node/react.css +7 -0
- package/dist/lib/node/react.css.map +7 -0
- package/dist/lib/node/testing/index.cjs +181 -0
- package/dist/lib/node/testing/index.cjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/react.css +7 -0
- package/dist/lib/node-esm/react.css.map +7 -0
- package/dist/lib/node-esm/react.mjs +4809 -0
- package/dist/lib/node-esm/react.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +161 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/components/CompoundButton/CompoundButton.stories.js +1 -1
- package/dist/types/src/components/CompoundButton/CompoundButton.stories.js.map +1 -1
- package/dist/types/src/components/DeviceList/DeviceList.d.ts +1 -1
- package/dist/types/src/components/DeviceList/DeviceList.d.ts.map +1 -1
- package/dist/types/src/components/DeviceList/DeviceList.js +2 -2
- package/dist/types/src/components/DeviceList/DeviceList.js.map +1 -1
- package/dist/types/src/components/DeviceList/DeviceListItem.d.ts.map +1 -1
- package/dist/types/src/components/DeviceList/DeviceListItem.js +4 -1
- package/dist/types/src/components/DeviceList/DeviceListItem.js.map +1 -1
- package/dist/types/src/components/DeviceList/DeviceListProps.d.ts +2 -0
- package/dist/types/src/components/DeviceList/DeviceListProps.d.ts.map +1 -1
- package/dist/types/src/components/IdentityList/SpaceMemberList.stories.js +3 -3
- package/dist/types/src/components/IdentityList/SpaceMemberList.stories.js.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationList.stories.js +11 -11
- package/dist/types/src/components/InvitationList/InvitationList.stories.js.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListContainer.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListContainer.js +2 -2
- package/dist/types/src/components/InvitationList/InvitationListContainer.js.map +1 -1
- package/dist/types/src/components/Panel/Panel.stories.js +1 -1
- package/dist/types/src/components/Panel/Panel.stories.js.map +1 -1
- package/dist/types/src/components/Viewport/Viewport.stories.js +1 -1
- package/dist/types/src/components/Viewport/Viewport.stories.js.map +1 -1
- package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -1
- package/dist/types/src/composites/Shell/Shell.js +11 -1
- package/dist/types/src/composites/Shell/Shell.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +43 -24
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +2 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts +1 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.js +2 -0
- package/dist/types/src/panels/IdentityPanel/identityMachine.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts +3 -5
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +5 -3
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
- package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js +1 -1
- package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js.map +1 -1
- package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts +1 -1
- package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/joinMachine.js +6 -0
- package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
- package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js +1 -3
- package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js.map +1 -1
- package/dist/types/src/panels/JoinPanel/steps/IdentityInput.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/steps/IdentityInput.js +17 -7
- package/dist/types/src/panels/JoinPanel/steps/IdentityInput.js.map +1 -1
- package/dist/types/src/panels/Panels.stories.js +1 -1
- package/dist/types/src/panels/Panels.stories.js.map +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js +16 -16
- package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js.map +1 -1
- package/dist/types/src/playwright/invitations-manager.d.ts +1 -2
- package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/playwright/invitations-manager.js +4 -5
- package/dist/types/src/playwright/invitations-manager.js.map +1 -1
- package/dist/types/src/playwright/invitations.spec.js +13 -25
- package/dist/types/src/playwright/invitations.spec.js.map +1 -1
- package/dist/types/src/steps/ConfirmReset.d.ts +1 -1
- package/dist/types/src/steps/ConfirmReset.d.ts.map +1 -1
- package/dist/types/src/steps/ConfirmReset.js +6 -2
- package/dist/types/src/steps/ConfirmReset.js.map +1 -1
- package/dist/types/src/stories/Invitations.e2e-stories.d.ts +1 -3
- package/dist/types/src/stories/Invitations.e2e-stories.d.ts.map +1 -1
- package/dist/types/src/stories/Invitations.e2e-stories.js +14 -6
- package/dist/types/src/stories/Invitations.e2e-stories.js.map +1 -1
- package/dist/types/src/testing/index.d.ts +0 -1
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/index.js +1 -1
- package/dist/types/src/testing/index.js.map +1 -1
- package/dist/types/src/translations/locales/en-US.d.ts +2 -0
- package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
- package/dist/types/src/translations/locales/en-US.js +2 -0
- package/dist/types/src/translations/locales/en-US.js.map +1 -1
- package/package.json +39 -28
- package/src/components/CompoundButton/CompoundButton.stories.tsx +1 -1
- package/src/components/DeviceList/DeviceList.tsx +2 -1
- package/src/components/DeviceList/DeviceListItem.tsx +8 -0
- package/src/components/DeviceList/DeviceListProps.ts +2 -0
- package/src/components/IdentityList/SpaceMemberList.stories.tsx +2 -2
- package/src/components/InvitationList/InvitationList.stories.tsx +2 -2
- package/src/components/InvitationList/InvitationListContainer.tsx +6 -3
- package/src/components/Panel/Panel.stories.tsx +1 -1
- package/src/components/Viewport/Viewport.stories.tsx +1 -1
- package/src/composites/Shell/Shell.tsx +12 -1
- package/src/panels/IdentityPanel/IdentityPanel.stories.tsx +1 -1
- package/src/panels/IdentityPanel/IdentityPanel.tsx +78 -44
- package/src/panels/IdentityPanel/IdentityPanelProps.ts +2 -0
- package/src/panels/IdentityPanel/identityMachine.ts +3 -1
- package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +21 -10
- package/src/panels/JoinPanel/JoinPanel.stories.tsx +1 -1
- package/src/panels/JoinPanel/JoinPanelProps.ts +1 -1
- package/src/panels/JoinPanel/joinMachine.ts +7 -0
- package/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx +0 -2
- package/src/panels/JoinPanel/steps/IdentityInput.tsx +22 -10
- package/src/panels/Panels.stories.tsx +1 -1
- package/src/panels/SpacePanel/SpacePanel.stories.tsx +2 -2
- package/src/playwright/invitations-manager.ts +5 -5
- package/src/playwright/invitations.spec.ts +14 -25
- package/src/steps/ConfirmReset.tsx +13 -5
- package/src/stories/Invitations.e2e-stories.tsx +17 -10
- package/src/testing/index.ts +2 -1
- package/src/translations/locales/en-US.ts +2 -0
|
@@ -21,6 +21,7 @@ export type IdentityPanelImplProps = {
|
|
|
21
21
|
| 'device invitation manager'
|
|
22
22
|
| 'identity action chooser'
|
|
23
23
|
| 'confirm join new identity'
|
|
24
|
+
| 'confirm recover'
|
|
24
25
|
| 'confirm reset storage';
|
|
25
26
|
initialDisposition?: IdentityPanelInitialDisposition;
|
|
26
27
|
identity: Identity;
|
|
@@ -29,6 +30,7 @@ export type IdentityPanelImplProps = {
|
|
|
29
30
|
onChangeConnectionState?: (nextState: ConnectionState) => Promise<void>;
|
|
30
31
|
onUpdateProfile?: (profile: NonNullable<Identity['profile']>) => Promise<void>;
|
|
31
32
|
onResetStorage?: () => Promise<void>;
|
|
33
|
+
onRecover?: () => Promise<void>;
|
|
32
34
|
onJoinNewIdentity?: () => Promise<void>;
|
|
33
35
|
createInvitationUrl: (invitationCode: string) => string;
|
|
34
36
|
send?: (event: SingleOrArray<Event<IdentityEvent>>) => void;
|
|
@@ -21,7 +21,7 @@ type IdentityMachineContext = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
type IdentityChooseActionEvent = {
|
|
24
|
-
type: 'chooseResetStorage' | 'chooseJoinNewIdentity' | 'unchooseAction';
|
|
24
|
+
type: 'chooseResetStorage' | 'chooseRecoverIdentity' | 'chooseJoinNewIdentity' | 'unchooseAction';
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
type IdentitySelectDeviceInvitationEvent = {
|
|
@@ -67,6 +67,7 @@ const identityMachine = createMachine<IdentityMachineContext, IdentityEvent>(
|
|
|
67
67
|
choosingAction: {},
|
|
68
68
|
managingDeviceInvitation: {},
|
|
69
69
|
confirmingResetStorage: {},
|
|
70
|
+
confirmingRecover: {},
|
|
70
71
|
confirmingJoinNewIdentity: {},
|
|
71
72
|
},
|
|
72
73
|
on: {
|
|
@@ -74,6 +75,7 @@ const identityMachine = createMachine<IdentityMachineContext, IdentityEvent>(
|
|
|
74
75
|
deselectInvitation: { target: '.choosingAction', actions: ['unsetInvitation', 'log'] },
|
|
75
76
|
selectInvitation: { target: '.managingDeviceInvitation', actions: ['setInvitation', 'log'] },
|
|
76
77
|
chooseJoinNewIdentity: { target: '.confirmingJoinNewIdentity', actions: 'log' },
|
|
78
|
+
chooseRecoverIdentity: { target: '.confirmingRecover', actions: 'log' },
|
|
77
79
|
chooseResetStorage: { target: '.confirmingResetStorage', actions: 'log' },
|
|
78
80
|
},
|
|
79
81
|
},
|
|
@@ -9,7 +9,7 @@ import { useClient } from '@dxos/react-client';
|
|
|
9
9
|
import { useHaloInvitations, DeviceType } from '@dxos/react-client/halo';
|
|
10
10
|
import { Invitation, InvitationEncoder } from '@dxos/react-client/invitations';
|
|
11
11
|
|
|
12
|
-
import { AgentConfig, type AgentFormProps, DeviceList } from '../../../components';
|
|
12
|
+
import { AgentConfig, type AgentFormProps, DeviceList, type DeviceListProps } from '../../../components';
|
|
13
13
|
import { type IdentityPanelStepProps } from '../IdentityPanelProps';
|
|
14
14
|
|
|
15
15
|
export type IdentityActionChooserProps = IdentityPanelStepProps;
|
|
@@ -33,20 +33,30 @@ export const IdentityActionChooser = (props: IdentityPanelStepProps) => {
|
|
|
33
33
|
}
|
|
34
34
|
send?.({ type: 'selectInvitation', invitation });
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
const isProduction = client.config.values.runtime?.app?.env?.DX_ENVIRONMENT === 'production';
|
|
37
|
+
return (
|
|
38
|
+
<IdentityActionChooserImpl
|
|
39
|
+
{...props}
|
|
40
|
+
onClickAdd={createInvitation}
|
|
41
|
+
onClickJoinExisting={() => send?.({ type: 'chooseJoinNewIdentity' })}
|
|
42
|
+
onClickRecover={isProduction ? undefined : () => send?.({ type: 'chooseRecoverIdentity' })}
|
|
43
|
+
onClickReset={() => send?.({ type: 'chooseResetStorage' })}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
37
46
|
};
|
|
38
47
|
|
|
39
48
|
export type IdentityActionChooserImplProps = IdentityActionChooserProps &
|
|
40
|
-
Partial<AgentFormProps> &
|
|
41
|
-
|
|
42
|
-
};
|
|
49
|
+
Partial<AgentFormProps> &
|
|
50
|
+
Pick<DeviceListProps, 'onClickAdd' | 'onClickJoinExisting' | 'onClickRecover' | 'onClickReset'>;
|
|
43
51
|
|
|
44
52
|
export const IdentityActionChooserImpl = ({
|
|
45
|
-
send,
|
|
46
|
-
onCreateInvitationClick,
|
|
47
53
|
devices,
|
|
48
54
|
connectionState,
|
|
49
55
|
agentHostingEnabled,
|
|
56
|
+
onClickAdd,
|
|
57
|
+
onClickJoinExisting,
|
|
58
|
+
onClickRecover,
|
|
59
|
+
onClickReset,
|
|
50
60
|
...agentProps
|
|
51
61
|
}: IdentityActionChooserImplProps) => {
|
|
52
62
|
const managedDeviceAvailable = devices.find((device) => device.profile?.type === DeviceType.AGENT_MANAGED);
|
|
@@ -55,9 +65,10 @@ export const IdentityActionChooserImpl = ({
|
|
|
55
65
|
<DeviceList
|
|
56
66
|
devices={devices}
|
|
57
67
|
connectionState={connectionState}
|
|
58
|
-
onClickAdd={
|
|
59
|
-
onClickJoinExisting={
|
|
60
|
-
|
|
68
|
+
onClickAdd={onClickAdd}
|
|
69
|
+
onClickJoinExisting={onClickJoinExisting}
|
|
70
|
+
onClickRecover={onClickRecover}
|
|
71
|
+
onClickReset={onClickReset}
|
|
61
72
|
onAgentDestroy={agentProps.onAgentDestroy!}
|
|
62
73
|
/>
|
|
63
74
|
{!managedDeviceAvailable && agentHostingEnabled && <AgentConfig {...(agentProps as AgentFormProps)} />}
|
|
@@ -30,7 +30,7 @@ const JoinDialog = (args: Partial<JoinPanelImplProps>) => (
|
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
export default {
|
|
33
|
-
title: 'sdk/
|
|
33
|
+
title: 'sdk/shell/JoinPanel',
|
|
34
34
|
component: JoinDialog,
|
|
35
35
|
decorators: [withTheme],
|
|
36
36
|
parameters: { translations, chromatic: { disableSnapshot: false } },
|
|
@@ -14,7 +14,7 @@ import { type FailReason } from '../../types';
|
|
|
14
14
|
|
|
15
15
|
export type JoinPanelMode = 'default' | 'halo-only';
|
|
16
16
|
|
|
17
|
-
export type JoinPanelInitialDisposition = 'default' | 'accept-halo-invitation';
|
|
17
|
+
export type JoinPanelInitialDisposition = 'default' | 'accept-halo-invitation' | 'recover-identity';
|
|
18
18
|
|
|
19
19
|
export type JoinStepProps = Omit<StepProps, 'send' | 'onDone'> & {
|
|
20
20
|
send: JoinSend;
|
|
@@ -312,6 +312,11 @@ const joinMachine = createMachine<JoinMachineContext, JoinEvent>(
|
|
|
312
312
|
target: '#join.choosingIdentity.acceptingHaloInvitation',
|
|
313
313
|
actions: 'log',
|
|
314
314
|
},
|
|
315
|
+
{
|
|
316
|
+
cond: 'initiallyRecoveringIdentity',
|
|
317
|
+
target: '#join.choosingIdentity.recoveringIdentity',
|
|
318
|
+
actions: 'log',
|
|
319
|
+
},
|
|
315
320
|
{ cond: 'noSelectedIdentity', target: 'choosingIdentity', actions: 'log' },
|
|
316
321
|
{ target: 'acceptingSpaceInvitation', actions: 'log' },
|
|
317
322
|
],
|
|
@@ -364,6 +369,8 @@ const joinMachine = createMachine<JoinMachineContext, JoinEvent>(
|
|
|
364
369
|
noSelectedIdentity: ({ identity }, _event) => !identity,
|
|
365
370
|
initiallyAcceptingHaloInvitation: ({ identity, initialDisposition }, _event) =>
|
|
366
371
|
!identity && initialDisposition === 'accept-halo-invitation',
|
|
372
|
+
initiallyRecoveringIdentity: ({ identity, initialDisposition }, _event) =>
|
|
373
|
+
!identity && initialDisposition === 'recover-identity',
|
|
367
374
|
hasHaloUnredeemedCode: ({ halo }, _event) => !!halo.unredeemedCode,
|
|
368
375
|
noSpaceInvitation: ({ space }, _event) => !space.invitation && !space.unredeemedCode,
|
|
369
376
|
},
|
|
@@ -50,8 +50,6 @@ export const AdditionMethodChooser = (viewStateProps: AdditionMethodChooserProps
|
|
|
50
50
|
</CompoundButton>
|
|
51
51
|
<CompoundButton
|
|
52
52
|
{...sharedButtonProps}
|
|
53
|
-
// TODO(mykola): Implement recover.
|
|
54
|
-
disabled={true}
|
|
55
53
|
description={t('recover identity description')}
|
|
56
54
|
before={<Textbox className={getSize(6)} />}
|
|
57
55
|
onClick={() => send({ type: 'recoverIdentity' })}
|
|
@@ -28,16 +28,28 @@ export const IdentityInput = (props: IdentityInputProps) => {
|
|
|
28
28
|
const client = useClient();
|
|
29
29
|
const { t } = useTranslation('os');
|
|
30
30
|
const [validationMessage, setValidationMessage] = useState('');
|
|
31
|
-
const createIdentity = (
|
|
32
|
-
|
|
33
|
-
(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
const createIdentity = (value: string) => {
|
|
32
|
+
if (isRecover) {
|
|
33
|
+
void client.halo.recoverIdentity({ seedphrase: value }).then(
|
|
34
|
+
(identity) => {
|
|
35
|
+
send?.({ type: 'selectIdentity' as const, identity });
|
|
36
|
+
},
|
|
37
|
+
(error) => {
|
|
38
|
+
log.catch(error);
|
|
39
|
+
setValidationMessage(t('failed to recover identity message'));
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
} else {
|
|
43
|
+
void client.halo.createIdentity({ displayName: value }).then(
|
|
44
|
+
(identity) => {
|
|
45
|
+
send?.({ type: 'selectIdentity' as const, identity });
|
|
46
|
+
},
|
|
47
|
+
(error) => {
|
|
48
|
+
log.catch(error);
|
|
49
|
+
setValidationMessage(t('failed to create identity message'));
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
}
|
|
41
53
|
};
|
|
42
54
|
return <IdentityInputImpl {...props} onDisplayNameConfirm={createIdentity} validationMessage={validationMessage} />;
|
|
43
55
|
};
|
|
@@ -53,7 +53,7 @@ export const Default = (props: any) => {
|
|
|
53
53
|
Default.parameters = { layout: 'fullscreen' };
|
|
54
54
|
|
|
55
55
|
export default {
|
|
56
|
-
title: 'sdk/
|
|
56
|
+
title: 'sdk/shell/All',
|
|
57
57
|
decorators: [withTheme],
|
|
58
58
|
component: StoryRow,
|
|
59
59
|
parameters: { chromatic: { disableSnapshot: false }, translations: [osTranslations] },
|
|
@@ -17,7 +17,7 @@ import { SpaceManagerImpl } from './steps';
|
|
|
17
17
|
import { InvitationListItemImpl, SpaceMemberListImpl, InvitationList } from '../../components';
|
|
18
18
|
import { StorybookDialog } from '../../components/StorybookDialog';
|
|
19
19
|
import { InvitationManager, type InvitationManagerProps } from '../../steps';
|
|
20
|
-
import { inviteWithState } from '../../testing';
|
|
20
|
+
import { inviteWithState } from '../../testing/fixtures';
|
|
21
21
|
|
|
22
22
|
const noOpProps: SpacePanelImplProps = {
|
|
23
23
|
titleId: 'storybookSpacePanel__title',
|
|
@@ -28,7 +28,7 @@ const noOpProps: SpacePanelImplProps = {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export default {
|
|
31
|
-
title: 'sdk/
|
|
31
|
+
title: 'sdk/shell/SpacePanel',
|
|
32
32
|
component: SpacePanelImpl,
|
|
33
33
|
decorators: [withTheme],
|
|
34
34
|
parameters: { chromatic: { disableSnapshot: false } },
|
|
@@ -6,7 +6,6 @@ import { expect, type Browser, type ConsoleMessage } from '@playwright/test';
|
|
|
6
6
|
|
|
7
7
|
import { Trigger } from '@dxos/async';
|
|
8
8
|
import { type Invitation } from '@dxos/react-client/invitations';
|
|
9
|
-
import { ConnectionState } from '@dxos/react-client/mesh';
|
|
10
9
|
import { setupPage } from '@dxos/test-utils/playwright';
|
|
11
10
|
|
|
12
11
|
import { ScopedShellManager } from '../testing';
|
|
@@ -32,7 +31,7 @@ export class InvitationsManager extends ScopedShellManager {
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
const { page } = await setupPage(this._browser, {
|
|
35
|
-
url: storybookUrl('invitations--default'),
|
|
34
|
+
url: storybookUrl('sdk-shell-invitations--default'),
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
this.page = page;
|
|
@@ -56,9 +55,9 @@ export class InvitationsManager extends ScopedShellManager {
|
|
|
56
55
|
|
|
57
56
|
try {
|
|
58
57
|
await selector.waitFor({ timeout: 500 });
|
|
59
|
-
return
|
|
58
|
+
return 0;
|
|
60
59
|
} catch {
|
|
61
|
-
return
|
|
60
|
+
return 1;
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -144,7 +143,8 @@ export class InvitationsManager extends ScopedShellManager {
|
|
|
144
143
|
},
|
|
145
144
|
{ id, type, options },
|
|
146
145
|
);
|
|
147
|
-
|
|
146
|
+
|
|
147
|
+
return this._invitationCode.wait({ timeout: 1_000 });
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
async acceptInvitation(id: number, type: 'device' | 'space', invitation: string) {
|
|
@@ -5,11 +5,16 @@
|
|
|
5
5
|
import { expect, test } from '@playwright/test';
|
|
6
6
|
|
|
7
7
|
import { sleep } from '@dxos/async';
|
|
8
|
-
import { Invitation } from '@dxos/react-client/invitations';
|
|
9
|
-
import { ConnectionState } from '@dxos/react-client/mesh';
|
|
10
8
|
|
|
11
9
|
import { InvitationsManager } from './invitations-manager';
|
|
12
10
|
|
|
11
|
+
// TODO(wittjosiah): Can't import these because of ESM/CJS issues.
|
|
12
|
+
// import { Invitation } from '@dxos/react-client/invitations';
|
|
13
|
+
// import { ConnectionState } from '@dxos/react-client/mesh';
|
|
14
|
+
const InvitationAuthMethodNone = 0;
|
|
15
|
+
const ConnectionStateOffline = 0;
|
|
16
|
+
const ConnectionStateOnline = 1;
|
|
17
|
+
|
|
13
18
|
test.describe('Invitations', () => {
|
|
14
19
|
let manager: InvitationsManager;
|
|
15
20
|
|
|
@@ -44,7 +49,6 @@ test.describe('Invitations', () => {
|
|
|
44
49
|
await manager.acceptInvitation(1, 'device', invitation);
|
|
45
50
|
await manager.readyToAuthenticate('device', manager.peer(1));
|
|
46
51
|
await manager.authenticateInvitation('device', authCode, manager.peer(1));
|
|
47
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
48
52
|
|
|
49
53
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
50
54
|
});
|
|
@@ -52,11 +56,10 @@ test.describe('Invitations', () => {
|
|
|
52
56
|
test('no auth method', async () => {
|
|
53
57
|
await manager.createIdentity(0);
|
|
54
58
|
await manager.openPanel(0, 'devices');
|
|
55
|
-
const invitation = await manager.createInvitation(0, 'device', { authMethod:
|
|
59
|
+
const invitation = await manager.createInvitation(0, 'device', { authMethod: InvitationAuthMethodNone });
|
|
56
60
|
|
|
57
61
|
await manager.openPanel(1, 'identity');
|
|
58
62
|
await manager.acceptInvitation(1, 'device', invitation);
|
|
59
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
60
63
|
|
|
61
64
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
62
65
|
});
|
|
@@ -72,7 +75,6 @@ test.describe('Invitations', () => {
|
|
|
72
75
|
await manager.authenticateInvitation('device', '000000', manager.peer(1));
|
|
73
76
|
await manager.clearAuthCode('device', manager.peer(1));
|
|
74
77
|
await manager.authenticateInvitation('device', authCode, manager.peer(1));
|
|
75
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
76
78
|
|
|
77
79
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
78
80
|
});
|
|
@@ -99,7 +101,6 @@ test.describe('Invitations', () => {
|
|
|
99
101
|
await manager.invitationInputContinue('device', manager.peer(1));
|
|
100
102
|
await manager.clearAuthCode('device', manager.peer(1));
|
|
101
103
|
await manager.authenticateInvitation('device', authCode, manager.peer(1));
|
|
102
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
103
104
|
|
|
104
105
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
105
106
|
});
|
|
@@ -144,7 +145,6 @@ test.describe('Invitations', () => {
|
|
|
144
145
|
await manager.invitationInputContinue('device', manager.peer(1));
|
|
145
146
|
await manager.clearAuthCode('device', manager.peer(1));
|
|
146
147
|
await manager.authenticateInvitation('device', authCode, manager.peer(1));
|
|
147
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
148
148
|
|
|
149
149
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
150
150
|
});
|
|
@@ -160,14 +160,13 @@ test.describe('Invitations', () => {
|
|
|
160
160
|
await manager.acceptInvitation(1, 'device', invitation);
|
|
161
161
|
expect(await manager.readyToAuthenticate('device', manager.peer(1))).toBe(true);
|
|
162
162
|
await manager.toggleNetworkStatus(0);
|
|
163
|
-
expect(await manager.getNetworkStatus(0)).toEqual(
|
|
163
|
+
expect(await manager.getNetworkStatus(0)).toEqual(ConnectionStateOffline);
|
|
164
164
|
await manager.toggleNetworkStatus(0);
|
|
165
|
-
expect(await manager.getNetworkStatus(0)).toEqual(
|
|
165
|
+
expect(await manager.getNetworkStatus(0)).toEqual(ConnectionStateOnline);
|
|
166
166
|
await manager.resetInvitation(manager.peer(1));
|
|
167
167
|
await manager.invitationInputContinue('device', manager.peer(1));
|
|
168
168
|
await manager.clearAuthCode('device', manager.peer(1));
|
|
169
169
|
await manager.authenticateInvitation('device', authCode, manager.peer(1));
|
|
170
|
-
await manager.doneInvitation('device', manager.peer(1));
|
|
171
170
|
|
|
172
171
|
expect(await manager.getDisplayName(0)).toEqual(await manager.getDisplayName(1));
|
|
173
172
|
});
|
|
@@ -186,7 +185,6 @@ test.describe('Invitations', () => {
|
|
|
186
185
|
await manager.acceptInvitation(1, 'space', invitation);
|
|
187
186
|
await manager.readyToAuthenticate('space', manager.peer(1));
|
|
188
187
|
await manager.authenticateInvitation('space', authCode, manager.peer(1));
|
|
189
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
190
188
|
|
|
191
189
|
await manager.openPanel(0, 'spaces');
|
|
192
190
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -196,17 +194,15 @@ test.describe('Invitations', () => {
|
|
|
196
194
|
await manager.createIdentity(0);
|
|
197
195
|
await manager.createSpace(0);
|
|
198
196
|
await manager.openPanel(0, 1);
|
|
199
|
-
const invitation1 = await manager.createInvitation(0, 'space', { authMethod:
|
|
197
|
+
const invitation1 = await manager.createInvitation(0, 'space', { authMethod: InvitationAuthMethodNone });
|
|
200
198
|
const invitation2 = await manager.createInvitation(0, 'space');
|
|
201
199
|
|
|
202
200
|
await manager.createIdentity(1);
|
|
203
201
|
await manager.openPanel(1, 'join');
|
|
204
202
|
await manager.acceptInvitation(1, 'space', invitation1);
|
|
205
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
206
203
|
|
|
207
204
|
await manager.openPanel(1, 'join');
|
|
208
205
|
await manager.acceptInvitation(1, 'space', invitation2);
|
|
209
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
210
206
|
|
|
211
207
|
expect(await manager.getSpaceMembersCount(0)).toEqual(2);
|
|
212
208
|
});
|
|
@@ -215,12 +211,11 @@ test.describe('Invitations', () => {
|
|
|
215
211
|
await manager.createIdentity(0);
|
|
216
212
|
await manager.createSpace(0);
|
|
217
213
|
await manager.openPanel(0, 1);
|
|
218
|
-
const invitation = await manager.createInvitation(0, 'space', { authMethod:
|
|
214
|
+
const invitation = await manager.createInvitation(0, 'space', { authMethod: InvitationAuthMethodNone });
|
|
219
215
|
|
|
220
216
|
await manager.createIdentity(1);
|
|
221
217
|
await manager.openPanel(1, 'join');
|
|
222
218
|
await manager.acceptInvitation(1, 'space', invitation);
|
|
223
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
224
219
|
|
|
225
220
|
await manager.openPanel(0, 'spaces');
|
|
226
221
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -242,7 +237,6 @@ test.describe('Invitations', () => {
|
|
|
242
237
|
|
|
243
238
|
await manager.clearAuthCode('space', manager.peer(1));
|
|
244
239
|
await manager.authenticateInvitation('space', authCode, manager.peer(1));
|
|
245
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
246
240
|
|
|
247
241
|
await manager.openPanel(0, 'spaces');
|
|
248
242
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -272,7 +266,6 @@ test.describe('Invitations', () => {
|
|
|
272
266
|
await manager.invitationInputContinue('space', manager.peer(1));
|
|
273
267
|
await manager.clearAuthCode('space', manager.peer(1));
|
|
274
268
|
await manager.authenticateInvitation('space', authCode, manager.peer(1));
|
|
275
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
276
269
|
|
|
277
270
|
await manager.openPanel(0, 'spaces');
|
|
278
271
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -323,7 +316,6 @@ test.describe('Invitations', () => {
|
|
|
323
316
|
await manager.invitationInputContinue('space', manager.peer(1));
|
|
324
317
|
await manager.clearAuthCode('space', manager.peer(1));
|
|
325
318
|
await manager.authenticateInvitation('space', authCode, manager.peer(1));
|
|
326
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
327
319
|
|
|
328
320
|
await manager.openPanel(0, 'spaces');
|
|
329
321
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -342,14 +334,13 @@ test.describe('Invitations', () => {
|
|
|
342
334
|
await manager.acceptInvitation(1, 'space', invitation);
|
|
343
335
|
expect(await manager.readyToAuthenticate('space', manager.peer(1))).toBe(true);
|
|
344
336
|
await manager.toggleNetworkStatus(0);
|
|
345
|
-
expect(await manager.getNetworkStatus(0)).toEqual(
|
|
337
|
+
expect(await manager.getNetworkStatus(0)).toEqual(ConnectionStateOffline);
|
|
346
338
|
await manager.toggleNetworkStatus(0);
|
|
347
|
-
expect(await manager.getNetworkStatus(0)).toEqual(
|
|
339
|
+
expect(await manager.getNetworkStatus(0)).toEqual(ConnectionStateOnline);
|
|
348
340
|
await manager.resetInvitation(manager.peer(1));
|
|
349
341
|
await manager.invitationInputContinue('space', manager.peer(1));
|
|
350
342
|
await manager.clearAuthCode('space', manager.peer(1));
|
|
351
343
|
await manager.authenticateInvitation('space', authCode, manager.peer(1));
|
|
352
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
353
344
|
|
|
354
345
|
await manager.openPanel(0, 'spaces');
|
|
355
346
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -380,8 +371,6 @@ test.describe('Invitations', () => {
|
|
|
380
371
|
// Helps to ensure both auth codes are fully input (especially in webkit).
|
|
381
372
|
await sleep(100);
|
|
382
373
|
await manager.authenticateInvitation('space', authCode2, manager.peer(2));
|
|
383
|
-
await manager.doneInvitation('space', manager.peer(1));
|
|
384
|
-
await manager.doneInvitation('space', manager.peer(2));
|
|
385
374
|
|
|
386
375
|
await manager.openPanel(0, 'spaces');
|
|
387
376
|
expect(await manager.getSpaceName(0, 1)).toEqual(await manager.getSpaceName(1, 1));
|
|
@@ -15,7 +15,7 @@ import { Action, Actions, StepHeading, Input } from '../components';
|
|
|
15
15
|
type ConfirmResetOptions = Partial<{
|
|
16
16
|
onCancel: () => void;
|
|
17
17
|
onConfirm: () => Promise<void>;
|
|
18
|
-
mode: 'join new identity' | 'reset storage';
|
|
18
|
+
mode: 'join new identity' | 'recover' | 'reset storage';
|
|
19
19
|
}>;
|
|
20
20
|
|
|
21
21
|
export type ConfirmResetProps = StepProps & ConfirmResetOptions;
|
|
@@ -64,7 +64,8 @@ export const ConfirmResetImpl = ({
|
|
|
64
64
|
const { t } = useTranslation('os');
|
|
65
65
|
const confirmationValue = t('confirmation value');
|
|
66
66
|
const [inputValue, setInputValue] = useState('');
|
|
67
|
-
const testIdAffix =
|
|
67
|
+
const testIdAffix =
|
|
68
|
+
mode === 'join new identity' ? 'join-new-identity' : mode === 'recover' ? 'recover' : 'reset-storage';
|
|
68
69
|
return (
|
|
69
70
|
<>
|
|
70
71
|
<div role='none' className='grow flex flex-col gap-2 justify-center'>
|
|
@@ -79,9 +80,16 @@ export const ConfirmResetImpl = ({
|
|
|
79
80
|
{...{ validationMessage }}
|
|
80
81
|
label={
|
|
81
82
|
<StepHeading className='text-start mlb-2'>
|
|
82
|
-
{t(
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
{t(
|
|
84
|
+
mode === 'join new identity'
|
|
85
|
+
? 'join new identity input label'
|
|
86
|
+
: mode === 'recover'
|
|
87
|
+
? 'recover reset input label'
|
|
88
|
+
: 'reset storage input label',
|
|
89
|
+
{
|
|
90
|
+
confirmationValue,
|
|
91
|
+
},
|
|
92
|
+
)}
|
|
85
93
|
</StepHeading>
|
|
86
94
|
}
|
|
87
95
|
disabled={disabled}
|
|
@@ -14,7 +14,7 @@ import { type Space, type SpaceMember, useSpaces } from '@dxos/react-client/echo
|
|
|
14
14
|
import { useIdentity } from '@dxos/react-client/halo';
|
|
15
15
|
import { Invitation, InvitationEncoder } from '@dxos/react-client/invitations';
|
|
16
16
|
import { ConnectionState, useNetworkStatus } from '@dxos/react-client/mesh';
|
|
17
|
-
import {
|
|
17
|
+
import { useMultiClient, withMultiClientProvider } from '@dxos/react-client/testing';
|
|
18
18
|
import { Button, ButtonGroup, List } from '@dxos/react-ui';
|
|
19
19
|
import { getSize, groupSurface } from '@dxos/react-ui-theme';
|
|
20
20
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
@@ -24,7 +24,7 @@ import { IdentityPanel, JoinPanel, SpacePanel } from '../panels';
|
|
|
24
24
|
import { osTranslations } from '../translations';
|
|
25
25
|
|
|
26
26
|
export default {
|
|
27
|
-
title: 'Invitations',
|
|
27
|
+
title: 'sdk/shell/Invitations',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export type PanelType = Space | 'identity' | 'devices' | 'join';
|
|
@@ -113,8 +113,8 @@ const Panel = ({ id, panel, setPanel }: { id: number; panel?: PanelType; setPane
|
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
-
const Invitations = (
|
|
117
|
-
const { id }
|
|
116
|
+
const Invitations = () => {
|
|
117
|
+
const { id } = useMultiClient();
|
|
118
118
|
const client = useClient();
|
|
119
119
|
const networkStatus = useNetworkStatus().swarm;
|
|
120
120
|
const identity = useIdentity();
|
|
@@ -220,12 +220,19 @@ const Invitations = (args: { id: number; count: number }) => {
|
|
|
220
220
|
// The issue appears to be related to dynamic imports during client initialization.
|
|
221
221
|
// This does not seem to be a problem in other browsers nor in Safari in the app.
|
|
222
222
|
export const Default = {
|
|
223
|
-
render: (
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
render: () => {
|
|
224
|
+
return (
|
|
225
|
+
// TODO(wittjosiah): Factor out ClipboardProvider to react-ui and include in layout decorator.
|
|
226
|
+
<ClipboardProvider>
|
|
227
|
+
<Invitations />
|
|
228
|
+
</ClipboardProvider>
|
|
229
|
+
);
|
|
230
|
+
},
|
|
231
|
+
decorators: [
|
|
232
|
+
withMultiClientProvider({ numClients: 3 }),
|
|
233
|
+
withLayout({ tooltips: true, classNames: 'grid grid-cols-3' }),
|
|
234
|
+
withTheme,
|
|
235
|
+
],
|
|
229
236
|
parameters: {
|
|
230
237
|
chromatic: { disableSnapshot: true },
|
|
231
238
|
translations: [osTranslations],
|
package/src/testing/index.ts
CHANGED
|
@@ -153,4 +153,6 @@ export const os = {
|
|
|
153
153
|
'agent requested description':
|
|
154
154
|
'The agent service is creating an agent for you. Once the agent connects, it will display in the devices list.',
|
|
155
155
|
'authenticating label': 'Authenticating…',
|
|
156
|
+
'create recovery code label': 'Create recovery code',
|
|
157
|
+
'choose recover identity label': 'Recover identity',
|
|
156
158
|
};
|