@dxos/shell 0.4.4-main.fcf0b00 → 0.4.4-next.75bfacc
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 +9006 -9218
- package/dist/bundle/shell.mjs.map +1 -1
- package/dist/bundle/shell.umd.js +62 -62
- 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 +65 -34
- package/dist/lib/browser/react.mjs.map +3 -3
- package/dist/types/src/components/Clipboard/CopyButton.js +5 -5
- package/dist/types/src/components/Clipboard/CopyButton.js.map +1 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.d.ts +3 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.d.ts.map +1 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.js +3 -3
- package/dist/types/src/components/IdentityList/IdentityListItem.js.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListItem.d.ts +8 -5
- package/dist/types/src/components/InvitationList/InvitationListItem.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListItem.js +10 -10
- package/dist/types/src/components/InvitationList/InvitationListItem.js.map +1 -1
- package/dist/types/src/components/Panel/Action.js +3 -3
- package/dist/types/src/components/Panel/Action.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js +10 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js.map +1 -1
- package/dist/types/src/panels/JoinPanel/JoinPanel.stories.d.ts +1 -1
- package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.d.ts +2 -1
- package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js +6 -3
- package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js.map +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.js +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.js.map +1 -1
- package/dist/types/src/react.d.ts +1 -0
- package/dist/types/src/react.d.ts.map +1 -1
- package/dist/types/src/react.js +1 -0
- package/dist/types/src/react.js.map +1 -1
- package/dist/types/src/stories/Invitations.e2e-stories.js +1 -1
- package/dist/types/src/translations/locales/en-US.d.ts +3 -1
- package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
- package/dist/types/src/translations/locales/en-US.js +3 -1
- package/dist/types/src/translations/locales/en-US.js.map +1 -1
- package/package.json +19 -19
- package/src/components/Clipboard/CopyButton.tsx +5 -5
- package/src/components/IdentityList/IdentityListItem.tsx +28 -26
- package/src/components/InvitationList/InvitationListItem.tsx +42 -15
- package/src/components/Panel/Action.tsx +3 -3
- package/src/panels/IdentityPanel/IdentityPanel.tsx +1 -1
- package/src/panels/IdentityPanel/steps/ProfileForm.tsx +21 -5
- package/src/panels/JoinPanel/steps/ResetIdentity.tsx +13 -4
- package/src/panels/SpacePanel/SpacePanel.tsx +1 -1
- package/src/react.ts +1 -0
- package/src/stories/Invitations.e2e-stories.tsx +1 -1
- package/src/translations/locales/en-US.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/shell",
|
|
3
|
-
"version": "0.4.4-
|
|
3
|
+
"version": "0.4.4-next.75bfacc",
|
|
4
4
|
"description": "DXOS’s OS experiences",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -39,19 +39,19 @@
|
|
|
39
39
|
"react-qr-rounded": "^1.0.0",
|
|
40
40
|
"url-join": "^5.0.0",
|
|
41
41
|
"xstate": "^4.37.0",
|
|
42
|
-
"@dxos/async": "0.4.4-
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/client-services": "0.4.4-
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/log": "0.4.4-
|
|
49
|
-
"@dxos/react-client": "0.4.4-
|
|
50
|
-
"@dxos/react-ui": "0.4.4-
|
|
51
|
-
"@dxos/react-ui-
|
|
52
|
-
"@dxos/
|
|
53
|
-
"@dxos/
|
|
54
|
-
"@dxos/util": "0.4.4-
|
|
42
|
+
"@dxos/async": "0.4.4-next.75bfacc",
|
|
43
|
+
"@dxos/client-protocol": "0.4.4-next.75bfacc",
|
|
44
|
+
"@dxos/client-services": "0.4.4-next.75bfacc",
|
|
45
|
+
"@dxos/display-name": "0.4.4-next.75bfacc",
|
|
46
|
+
"@dxos/debug": "0.4.4-next.75bfacc",
|
|
47
|
+
"@dxos/invariant": "0.4.4-next.75bfacc",
|
|
48
|
+
"@dxos/log": "0.4.4-next.75bfacc",
|
|
49
|
+
"@dxos/react-client": "0.4.4-next.75bfacc",
|
|
50
|
+
"@dxos/react-ui": "0.4.4-next.75bfacc",
|
|
51
|
+
"@dxos/react-ui-types": "0.4.4-next.75bfacc",
|
|
52
|
+
"@dxos/rpc-tunnel": "0.4.4-next.75bfacc",
|
|
53
|
+
"@dxos/react-ui-theme": "0.4.4-next.75bfacc",
|
|
54
|
+
"@dxos/util": "0.4.4-next.75bfacc"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -63,11 +63,11 @@
|
|
|
63
63
|
"react-dom": "^18.2.0",
|
|
64
64
|
"vite": "^5.0.12",
|
|
65
65
|
"vite-plugin-turbosnap": "^1.0.2",
|
|
66
|
-
"@dxos/config": "0.4.4-
|
|
67
|
-
"@dxos/random": "0.4.4-
|
|
68
|
-
"@dxos/react-
|
|
69
|
-
"@dxos/react-
|
|
70
|
-
"@dxos/storybook-utils": "0.4.4-
|
|
66
|
+
"@dxos/config": "0.4.4-next.75bfacc",
|
|
67
|
+
"@dxos/random": "0.4.4-next.75bfacc",
|
|
68
|
+
"@dxos/react-async": "0.4.4-next.75bfacc",
|
|
69
|
+
"@dxos/react-ui-theme": "0.4.4-next.75bfacc",
|
|
70
|
+
"@dxos/storybook-utils": "0.4.4-next.75bfacc"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
73
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -30,11 +30,11 @@ export const CopyButton = ({ value, classNames, iconProps, ...props }: CopyButto
|
|
|
30
30
|
>
|
|
31
31
|
<div role='none' className={mx('flex gap-1 items-center', isCopied && inactiveLabelStyles)}>
|
|
32
32
|
<span className='pli-1'>{t('copy invitation code label')}</span>
|
|
33
|
-
<Copy className={getSize(
|
|
33
|
+
<Copy className={getSize(5)} {...iconProps} />
|
|
34
34
|
</div>
|
|
35
35
|
<div role='none' className={mx('flex gap-1 items-center', !isCopied && inactiveLabelStyles)}>
|
|
36
|
-
<span className='pli-1'>{t('copy
|
|
37
|
-
<Check className={getSize(
|
|
36
|
+
<span className='pli-1'>{t('copy success label')}</span>
|
|
37
|
+
<Check className={getSize(5)} {...iconProps} />
|
|
38
38
|
</div>
|
|
39
39
|
</Button>
|
|
40
40
|
);
|
|
@@ -44,7 +44,7 @@ export const CopyButtonIconOnly = ({ value, classNames, iconProps, variant, ...p
|
|
|
44
44
|
const { t } = useTranslation('os');
|
|
45
45
|
const { textValue, setTextValue } = useClipboardContext();
|
|
46
46
|
const isCopied = textValue === value;
|
|
47
|
-
const label = isCopied ? t('copy
|
|
47
|
+
const label = isCopied ? t('copy success label') : t('copy invitation code label');
|
|
48
48
|
const [open, setOpen] = useState(false);
|
|
49
49
|
return (
|
|
50
50
|
<Tooltip.Root delayDuration={1500} open={open} onOpenChange={setOpen}>
|
|
@@ -62,7 +62,7 @@ export const CopyButtonIconOnly = ({ value, classNames, iconProps, variant, ...p
|
|
|
62
62
|
asChild
|
|
63
63
|
>
|
|
64
64
|
<Button variant={variant} classNames={['inline-flex flex-col justify-center', classNames]}>
|
|
65
|
-
<Copy className={getSize(5)}
|
|
65
|
+
<Copy className={getSize(5)} {...iconProps} />
|
|
66
66
|
</Button>
|
|
67
67
|
</Tooltip.Trigger>
|
|
68
68
|
</Tooltip.Root>
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { forwardRef } from 'react';
|
|
5
|
+
import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
|
|
6
6
|
|
|
7
7
|
import { generateName } from '@dxos/display-name';
|
|
8
8
|
import { SpaceMember } from '@dxos/react-client/echo';
|
|
9
9
|
import { type Identity } from '@dxos/react-client/halo';
|
|
10
|
-
import { ListItem, Avatar, useJdenticonHref, useId } from '@dxos/react-ui';
|
|
10
|
+
import { ListItem, Avatar, useJdenticonHref, useId, type ThemedClassName } from '@dxos/react-ui';
|
|
11
11
|
import { mx } from '@dxos/react-ui-theme';
|
|
12
12
|
|
|
13
13
|
type IdentityListItemProps = {
|
|
@@ -16,27 +16,29 @@ type IdentityListItemProps = {
|
|
|
16
16
|
onClick?: () => void;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const IdentityListItem = forwardRef<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
export const IdentityListItem = forwardRef<
|
|
20
|
+
HTMLLIElement,
|
|
21
|
+
ThemedClassName<ComponentPropsWithoutRef<'li'>> & IdentityListItemProps
|
|
22
|
+
>(({ identity, presence, onClick, classNames, ...props }, forwardedRef) => {
|
|
23
|
+
const fallbackValue = identity.identityKey.toHex();
|
|
24
|
+
const labelId = useId('identityListItem__label');
|
|
25
|
+
const jdenticon = useJdenticonHref(fallbackValue ?? '', 12);
|
|
26
|
+
const displayName = identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
|
|
27
|
+
return (
|
|
28
|
+
<ListItem.Root
|
|
29
|
+
{...props}
|
|
30
|
+
classNames={mx('flex gap-2 pis-3 pie-1 items-center', onClick && 'cursor-pointer', classNames)}
|
|
31
|
+
onClick={() => onClick?.()}
|
|
32
|
+
data-testid='identity-list-item'
|
|
33
|
+
labelId={labelId}
|
|
34
|
+
ref={forwardedRef}
|
|
35
|
+
>
|
|
36
|
+
<Avatar.Root status={presence === SpaceMember.PresenceState.ONLINE ? 'active' : 'inactive'} labelId={labelId}>
|
|
37
|
+
<Avatar.Frame classNames='place-self-center'>
|
|
38
|
+
<Avatar.Fallback href={jdenticon} />
|
|
39
|
+
</Avatar.Frame>
|
|
40
|
+
<Avatar.Label classNames='text-sm truncate pli-2'>{displayName}</Avatar.Label>
|
|
41
|
+
</Avatar.Root>
|
|
42
|
+
</ListItem.Root>
|
|
43
|
+
);
|
|
44
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
import { X } from '@phosphor-icons/react';
|
|
5
|
-
import React, { useCallback } from 'react';
|
|
5
|
+
import React, { type ComponentPropsWithoutRef, useCallback } from 'react';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
type CancellableInvitationObservable,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
useThemeContext,
|
|
19
19
|
type AvatarRootProps,
|
|
20
20
|
Tooltip,
|
|
21
|
+
type ThemedClassName,
|
|
21
22
|
} from '@dxos/react-ui';
|
|
22
23
|
import { focusRing, getSize, mx } from '@dxos/react-ui-theme';
|
|
23
24
|
|
|
@@ -26,14 +27,15 @@ import { toEmoji } from '../../util';
|
|
|
26
27
|
import { AuthCode } from '../AuthCode';
|
|
27
28
|
import { CopyButtonIconOnly } from '../Clipboard';
|
|
28
29
|
|
|
29
|
-
export
|
|
30
|
+
export type InvitationListItemProps = SharedInvitationListProps & {
|
|
30
31
|
invitation: CancellableInvitationObservable;
|
|
31
32
|
onClickRemove?: (invitation: CancellableInvitationObservable) => void;
|
|
32
|
-
|
|
33
|
+
reverseEffects?: boolean;
|
|
34
|
+
} & ThemedClassName<ComponentPropsWithoutRef<'li'>>;
|
|
33
35
|
|
|
34
|
-
export
|
|
36
|
+
export type InvitationListItemImplProps = InvitationListItemProps & {
|
|
35
37
|
invitationStatus: InvitationStatus;
|
|
36
|
-
}
|
|
38
|
+
};
|
|
37
39
|
|
|
38
40
|
export const InvitationListItem = (props: InvitationListItemProps) => {
|
|
39
41
|
const { invitation } = props;
|
|
@@ -43,13 +45,21 @@ export const InvitationListItem = (props: InvitationListItemProps) => {
|
|
|
43
45
|
|
|
44
46
|
const avatarProps: Pick<AvatarRootProps, 'size' | 'variant'> = { size: 10, variant: 'circle' };
|
|
45
47
|
|
|
46
|
-
const AvatarStackEffect = ({
|
|
48
|
+
const AvatarStackEffect = ({
|
|
49
|
+
animation,
|
|
50
|
+
status,
|
|
51
|
+
reverseEffects,
|
|
52
|
+
}: Pick<AvatarRootProps, 'status' | 'animation'> & Pick<InvitationListItemProps, 'reverseEffects'>) => {
|
|
47
53
|
const { tx } = useThemeContext();
|
|
48
54
|
return (
|
|
49
55
|
<>
|
|
50
56
|
<span
|
|
51
57
|
role='none'
|
|
52
|
-
className={mx(
|
|
58
|
+
className={mx(
|
|
59
|
+
'absolute inline-end-auto opacity-20',
|
|
60
|
+
reverseEffects ? 'inline-start-3' : 'inline-start-1',
|
|
61
|
+
getSize(avatarProps.size!),
|
|
62
|
+
)}
|
|
53
63
|
>
|
|
54
64
|
<span
|
|
55
65
|
role='none'
|
|
@@ -59,7 +69,11 @@ const AvatarStackEffect = ({ animation, status }: Pick<AvatarRootProps, 'status'
|
|
|
59
69
|
</span>
|
|
60
70
|
<span
|
|
61
71
|
role='none'
|
|
62
|
-
className={mx(
|
|
72
|
+
className={mx(
|
|
73
|
+
'absolute inline-end-auto opacity-50',
|
|
74
|
+
reverseEffects ? 'inline-start-2' : 'inline-start-2',
|
|
75
|
+
getSize(avatarProps.size!),
|
|
76
|
+
)}
|
|
63
77
|
>
|
|
64
78
|
<span
|
|
65
79
|
role='none'
|
|
@@ -77,6 +91,8 @@ export const InvitationListItemImpl = ({
|
|
|
77
91
|
send,
|
|
78
92
|
onClickRemove,
|
|
79
93
|
createInvitationUrl,
|
|
94
|
+
reverseEffects,
|
|
95
|
+
...props
|
|
80
96
|
}: InvitationListItemImplProps) => {
|
|
81
97
|
const { t } = useTranslation('os');
|
|
82
98
|
const { cancel, status: invitationStatus, invitationCode, authCode, type } = propsInvitationStatus;
|
|
@@ -120,15 +136,21 @@ export const InvitationListItemImpl = ({
|
|
|
120
136
|
const avatarStatus = avatarError ? 'error' : avatarGreen ? 'active' : 'inactive';
|
|
121
137
|
|
|
122
138
|
return (
|
|
123
|
-
<ListItem.Root
|
|
139
|
+
<ListItem.Root
|
|
140
|
+
id={invitationCode}
|
|
141
|
+
{...props}
|
|
142
|
+
classNames={['flex gap-2 pis-3 pie-1 items-center relative', props.classNames]}
|
|
143
|
+
>
|
|
124
144
|
<ListItem.Heading classNames='sr-only'>
|
|
125
145
|
{t(type === Invitation.Type.MULTIUSE ? 'invite many list item label' : 'invite one list item label')}
|
|
126
146
|
</ListItem.Heading>
|
|
127
|
-
{type === Invitation.Type.MULTIUSE &&
|
|
147
|
+
{type === Invitation.Type.MULTIUSE && (
|
|
148
|
+
<AvatarStackEffect status={avatarStatus} animation={avatarAnimation} reverseEffects={reverseEffects} />
|
|
149
|
+
)}
|
|
128
150
|
<Tooltip.Root>
|
|
129
151
|
<Avatar.Root {...avatarProps} animation={avatarAnimation} status={avatarStatus}>
|
|
130
152
|
<Tooltip.Trigger asChild>
|
|
131
|
-
<Avatar.Frame tabIndex={0} classNames={[focusRing, 'relative rounded-full']}>
|
|
153
|
+
<Avatar.Frame tabIndex={0} classNames={[focusRing, 'relative rounded-full place-self-center']}>
|
|
132
154
|
<Avatar.Fallback text={toEmoji(invitationId)} />
|
|
133
155
|
</Avatar.Frame>
|
|
134
156
|
</Tooltip.Trigger>
|
|
@@ -168,14 +190,19 @@ export const InvitationListItemImpl = ({
|
|
|
168
190
|
<span className='grow'> </span>
|
|
169
191
|
)}
|
|
170
192
|
{isCancellable ? (
|
|
171
|
-
<Button variant='ghost' classNames='flex gap-1' onClick={cancel} data-testid='cancel-invitation'>
|
|
193
|
+
<Button variant='ghost' classNames='flex gap-1 pli-0' onClick={cancel} data-testid='cancel-invitation'>
|
|
172
194
|
<span className='sr-only'>{t('cancel invitation label')}</span>
|
|
173
|
-
<X className={getSize(
|
|
195
|
+
<X className={getSize(4)} />
|
|
174
196
|
</Button>
|
|
175
197
|
) : (
|
|
176
|
-
<Button
|
|
198
|
+
<Button
|
|
199
|
+
variant='ghost'
|
|
200
|
+
classNames='flex gap-1 pli-0'
|
|
201
|
+
onClick={handleClickRemove}
|
|
202
|
+
data-testid='remove-invitation'
|
|
203
|
+
>
|
|
177
204
|
<span className='sr-only'>{t('remove invitation label')}</span>
|
|
178
|
-
<X className={getSize(
|
|
205
|
+
<X className={getSize(4)} />
|
|
179
206
|
</Button>
|
|
180
207
|
)}
|
|
181
208
|
</ListItem.Root>
|
|
@@ -66,14 +66,14 @@ export const BifurcatedAction = forwardRef<HTMLButtonElement, BifurcatedActionPr
|
|
|
66
66
|
variant={variant}
|
|
67
67
|
onClick={activeAction.onClick}
|
|
68
68
|
>
|
|
69
|
-
{activeAction.icon && <activeAction.icon />}
|
|
69
|
+
{activeAction.icon && <activeAction.icon className={getSize(5)} />}
|
|
70
70
|
<span>{activeAction.label}</span>
|
|
71
71
|
</Button>
|
|
72
72
|
<DropdownMenu.Root>
|
|
73
73
|
<DropdownMenu.Trigger asChild>
|
|
74
74
|
<Button classNames={['bs-11 flex-none rounded-is-none', classNames]}>
|
|
75
75
|
<span className='sr-only'>{t('invite options label')}</span>
|
|
76
|
-
<CaretDown />
|
|
76
|
+
<CaretDown className={getSize(4)} />
|
|
77
77
|
</Button>
|
|
78
78
|
</DropdownMenu.Trigger>
|
|
79
79
|
{/* TODO(thure): Putting `DropdownMenu.Portal` here breaks highlighting and focus. Why? */}
|
|
@@ -99,7 +99,7 @@ export const BifurcatedAction = forwardRef<HTMLButtonElement, BifurcatedActionPr
|
|
|
99
99
|
)}
|
|
100
100
|
</div>
|
|
101
101
|
<DropdownMenu.ItemIndicator asChild>
|
|
102
|
-
<Check />
|
|
102
|
+
<Check weight='bold' className={getSize(4)} />
|
|
103
103
|
</DropdownMenu.ItemIndicator>
|
|
104
104
|
</DropdownMenu.CheckboxItem>
|
|
105
105
|
);
|
|
@@ -87,7 +87,7 @@ export const IdentityPanelImpl = (props: IdentityPanelImplProps) => {
|
|
|
87
87
|
<ProfileForm
|
|
88
88
|
send={rest.send}
|
|
89
89
|
active={activeView === 'update profile form'}
|
|
90
|
-
|
|
90
|
+
identity={identity}
|
|
91
91
|
onUpdateProfile={onUpdateProfile}
|
|
92
92
|
/>
|
|
93
93
|
</Viewport.View>
|
|
@@ -9,14 +9,14 @@ import { log } from '@dxos/log';
|
|
|
9
9
|
import { type Identity } from '@dxos/react-client/halo';
|
|
10
10
|
import { useTranslation } from '@dxos/react-ui';
|
|
11
11
|
|
|
12
|
-
import { Action, Actions, StepHeading, Input } from '../../../components';
|
|
12
|
+
import { Action, Actions, StepHeading, Input, useClipboardContext } from '../../../components';
|
|
13
13
|
import { type IdentityPanelStepProps } from '../IdentityPanelProps';
|
|
14
14
|
import { type IdentityEvent } from '../identityMachine';
|
|
15
15
|
|
|
16
16
|
export interface ProfileFormProps extends Omit<IdentityPanelStepProps, 'send'> {
|
|
17
17
|
send?: (event: SingleOrArray<Event<IdentityEvent>>) => void;
|
|
18
18
|
onUpdateProfile?: (profile: NonNullable<Identity['profile']>) => Promise<void>;
|
|
19
|
-
|
|
19
|
+
identity?: Identity;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export type ProfileFormImplProps = ProfileFormProps & {
|
|
@@ -38,10 +38,14 @@ export const ProfileForm = (props: ProfileFormProps) => {
|
|
|
38
38
|
|
|
39
39
|
// TODO(zhenyasav): impl shouldn't need send()
|
|
40
40
|
const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
41
|
-
const { active,
|
|
41
|
+
const { active, identity, send, onUpdateProfile, validationMessage } = props;
|
|
42
|
+
const profile = identity?.profile;
|
|
42
43
|
const disabled = !active;
|
|
43
44
|
const { t } = useTranslation('os');
|
|
44
45
|
const [inputValue, setInputValue] = useState(profile?.displayName ?? '');
|
|
46
|
+
const { textValue, setTextValue } = useClipboardContext();
|
|
47
|
+
const identityHex = identity?.identityKey.toHex();
|
|
48
|
+
const copied = textValue === identityHex;
|
|
45
49
|
return (
|
|
46
50
|
<>
|
|
47
51
|
<div role='none' className='grow flex flex-col justify-center'>
|
|
@@ -57,11 +61,23 @@ const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
|
57
61
|
/>
|
|
58
62
|
</div>
|
|
59
63
|
<Actions>
|
|
64
|
+
<Action
|
|
65
|
+
variant='ghost'
|
|
66
|
+
disabled={disabled}
|
|
67
|
+
onClick={() => {
|
|
68
|
+
if (identityHex) {
|
|
69
|
+
void setTextValue(identityHex);
|
|
70
|
+
}
|
|
71
|
+
}}
|
|
72
|
+
data-testid='update-profile-form-copy-key'
|
|
73
|
+
>
|
|
74
|
+
{t(copied ? 'copy success label' : 'copy self public key label')}
|
|
75
|
+
</Action>
|
|
60
76
|
<Action
|
|
61
77
|
variant='ghost'
|
|
62
78
|
disabled={disabled}
|
|
63
79
|
onClick={() => send?.({ type: 'unchooseAction' })}
|
|
64
|
-
data-testid=
|
|
80
|
+
data-testid='update-profile-form-back'
|
|
65
81
|
>
|
|
66
82
|
{t('back label')}
|
|
67
83
|
</Action>
|
|
@@ -69,7 +85,7 @@ const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
|
69
85
|
variant='primary'
|
|
70
86
|
disabled={disabled}
|
|
71
87
|
onClick={() => onUpdateProfile?.({ displayName: inputValue })}
|
|
72
|
-
data-testid=
|
|
88
|
+
data-testid='update-profile-form-continue'
|
|
73
89
|
>
|
|
74
90
|
{t('done label')}
|
|
75
91
|
</Action>
|
|
@@ -17,6 +17,7 @@ export type ResetIdentityProps = JoinStepProps & {
|
|
|
17
17
|
|
|
18
18
|
export type ResetIdentityImplProps = {
|
|
19
19
|
disabled?: boolean;
|
|
20
|
+
pending?: boolean;
|
|
20
21
|
validationMessage?: string;
|
|
21
22
|
onConfirm?: () => void;
|
|
22
23
|
};
|
|
@@ -25,21 +26,29 @@ export const ResetIdentity = ({ send, active }: ResetIdentityProps) => {
|
|
|
25
26
|
const client = useClient();
|
|
26
27
|
const { t } = useTranslation('os');
|
|
27
28
|
const [validationMessage, setValidationMessage] = useState('');
|
|
29
|
+
const [pending, setPending] = useState(false);
|
|
28
30
|
const resetIdentity = () => {
|
|
31
|
+
setPending(true);
|
|
29
32
|
void client.reset().then(
|
|
30
33
|
() => send?.({ type: 'resetIdentity' }),
|
|
31
34
|
(error) => {
|
|
32
35
|
log.catch(error);
|
|
33
36
|
setValidationMessage(t('failed to reset identity message'));
|
|
37
|
+
setPending(false);
|
|
34
38
|
},
|
|
35
39
|
);
|
|
36
40
|
};
|
|
37
41
|
return (
|
|
38
|
-
<ResetIdentityImpl
|
|
42
|
+
<ResetIdentityImpl
|
|
43
|
+
disabled={!active}
|
|
44
|
+
pending={pending}
|
|
45
|
+
validationMessage={validationMessage}
|
|
46
|
+
onConfirm={() => resetIdentity()}
|
|
47
|
+
/>
|
|
39
48
|
);
|
|
40
49
|
};
|
|
41
50
|
|
|
42
|
-
export const ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }: ResetIdentityImplProps) => {
|
|
51
|
+
export const ResetIdentityImpl = ({ disabled, pending, validationMessage, onConfirm }: ResetIdentityImplProps) => {
|
|
43
52
|
const { t } = useTranslation('os');
|
|
44
53
|
const confirmationValue = t('confirmation value');
|
|
45
54
|
const [inputValue, setInputValue] = useState('');
|
|
@@ -59,11 +68,11 @@ export const ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }: Re
|
|
|
59
68
|
<Action
|
|
60
69
|
// TODO(wittjosiah): Probably make this red?
|
|
61
70
|
variant='primary'
|
|
62
|
-
disabled={disabled || inputValue !== confirmationValue}
|
|
71
|
+
disabled={disabled || pending || inputValue !== confirmationValue}
|
|
63
72
|
onClick={() => onConfirm?.()}
|
|
64
73
|
data-testid='reset-identity-input-confirm'
|
|
65
74
|
>
|
|
66
|
-
{t('confirm label')}
|
|
75
|
+
{pending ? t('reset in progress label') : t('confirm label')}
|
|
67
76
|
</Action>
|
|
68
77
|
</Actions>
|
|
69
78
|
</>
|
|
@@ -27,7 +27,7 @@ const SpacePanelHeading = ({ titleId, space, onDone }: SpacePanelHeadingProps) =
|
|
|
27
27
|
corner={<CloseButton data-testid='identity-panel-done' onDone={onDone} />}
|
|
28
28
|
>
|
|
29
29
|
<div role='none' className='flex gap-4 items-center justify-center mlb-4'>
|
|
30
|
-
<Planet size={32} />
|
|
30
|
+
<Planet size={32} weight='light' />
|
|
31
31
|
<div className='block text-start font-light text-xl'>{name ?? space.key.truncate()}</div>
|
|
32
32
|
</div>
|
|
33
33
|
</Heading>
|
package/src/react.ts
CHANGED
|
@@ -219,7 +219,7 @@ export const Default = {
|
|
|
219
219
|
render: (args: { id: number }) => (
|
|
220
220
|
<ClipboardProvider>
|
|
221
221
|
<Tooltip.Provider>
|
|
222
|
-
<ClientRepeater
|
|
222
|
+
<ClientRepeater component={Invitations} count={3} />
|
|
223
223
|
</Tooltip.Provider>
|
|
224
224
|
</ClipboardProvider>
|
|
225
225
|
),
|
|
@@ -7,7 +7,8 @@ export const os = {
|
|
|
7
7
|
'identity offline description': 'Offline',
|
|
8
8
|
'sidebar label': 'DXOS sidebar',
|
|
9
9
|
'copy invitation code label': 'Copy URL',
|
|
10
|
-
'copy
|
|
10
|
+
'copy success label': 'Copied',
|
|
11
|
+
'copy self public key label': 'Copy public key',
|
|
11
12
|
'open share panel label': 'View QR code',
|
|
12
13
|
'joining space heading': 'Joining space',
|
|
13
14
|
'join space heading': 'Enter space invitation',
|
|
@@ -94,6 +95,7 @@ export const os = {
|
|
|
94
95
|
'invite many qr label': 'Multiple-use',
|
|
95
96
|
'invite many list item label': 'Active multiple-use invitation',
|
|
96
97
|
'invite options label': 'Change the active invite option.',
|
|
98
|
+
'reset in progress label': 'Resetting...',
|
|
97
99
|
'confirm label': 'Confirm',
|
|
98
100
|
'reset identity input label':
|
|
99
101
|
'This will clear this device and all associated data. Type {{confirmationValue}} and confirm to continue.',
|