@dxos/shell 0.6.14-main.f49f251 → 0.6.14-staging.8758a12
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 +1365 -1355
- package/dist/bundle/shell.mjs.map +1 -1
- package/dist/bundle/shell.umd.js +29 -29
- 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 +11 -8
- package/dist/lib/browser/react.mjs.map +3 -3
- 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 +4766 -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 +4812 -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/IdentityList/SpaceMemberList.stories.js +2 -2
- package/dist/types/src/components/IdentityList/SpaceMemberList.stories.js.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationList.stories.js +10 -10
- package/dist/types/src/components/InvitationList/InvitationList.stories.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +13 -6
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +1 -0
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.js +5 -0
- package/dist/types/src/panels/IdentityPanel/useEdgeAgentsHandlers.js.map +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js +15 -15
- 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 +2 -3
- package/dist/types/src/playwright/invitations-manager.js.map +1 -1
- package/dist/types/src/playwright/invitations.spec.js +13 -9
- package/dist/types/src/playwright/invitations.spec.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/package.json +38 -27
- package/src/components/IdentityList/SpaceMemberList.stories.tsx +1 -1
- package/src/components/InvitationList/InvitationList.stories.tsx +1 -1
- package/src/panels/IdentityPanel/IdentityPanel.tsx +13 -3
- package/src/panels/IdentityPanel/IdentityPanelProps.ts +1 -0
- package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +1 -1
- package/src/panels/IdentityPanel/useEdgeAgentsHandlers.ts +7 -0
- package/src/panels/SpacePanel/SpacePanel.stories.tsx +1 -1
- package/src/playwright/invitations-manager.ts +2 -3
- package/src/playwright/invitations.spec.ts +14 -9
- package/src/testing/index.ts +2 -1
|
@@ -0,0 +1,4812 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
__export
|
|
4
|
+
} from "./chunk-HSLMI22Q.mjs";
|
|
5
|
+
|
|
6
|
+
// packages/sdk/shell/src/components/AgentConfig.tsx
|
|
7
|
+
import { ArrowsClockwise, Database, Plus, Power } from "@phosphor-icons/react";
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { Avatar, Button, Link, Tooltip, Trans, useTranslation } from "@dxos/react-ui";
|
|
10
|
+
import { descriptionText, getSize, mx, valenceColorText } from "@dxos/react-ui-theme";
|
|
11
|
+
var AgentConfig = ({ agentStatus, validationMessage, onAgentDestroy, onAgentCreate, onAgentRefresh }) => {
|
|
12
|
+
const { t } = useTranslation("os");
|
|
13
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h2", {
|
|
14
|
+
className: mx(descriptionText, "text-center mbs-4")
|
|
15
|
+
}, t("agent heading")), validationMessage && /* @__PURE__ */ React.createElement("p", {
|
|
16
|
+
role: "alert",
|
|
17
|
+
className: mx(valenceColorText("error"), "mlb-2")
|
|
18
|
+
}, validationMessage), agentStatus === "created" || agentStatus === "creating" || agentStatus === "getting" || agentStatus === "destroying" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
19
|
+
role: "group",
|
|
20
|
+
className: "mlb-2 flex gap-2 items-center",
|
|
21
|
+
"aria-describedby": "devices-panel.create-agent.description"
|
|
22
|
+
}, /* @__PURE__ */ React.createElement(Avatar.Root, {
|
|
23
|
+
status: agentStatus === "created" ? "warning" : "inactive",
|
|
24
|
+
variant: "square"
|
|
25
|
+
}, /* @__PURE__ */ React.createElement(Avatar.Frame, {
|
|
26
|
+
classNames: "place-self-center"
|
|
27
|
+
}, /* @__PURE__ */ React.createElement(Database, {
|
|
28
|
+
weight: "duotone",
|
|
29
|
+
width: 24,
|
|
30
|
+
height: 24,
|
|
31
|
+
x: 8,
|
|
32
|
+
y: 8,
|
|
33
|
+
...agentStatus !== "created" && {
|
|
34
|
+
className: "opacity-50"
|
|
35
|
+
}
|
|
36
|
+
})), /* @__PURE__ */ React.createElement(Avatar.Label, {
|
|
37
|
+
classNames: "flex-1 text-sm truncate"
|
|
38
|
+
}, t(agentStatus === "created" ? "agent requested label" : agentStatus === "creating" ? "creating agent label" : agentStatus === "destroying" ? "destroying agent label" : "getting agent label"))), agentStatus === "created" && /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
|
|
39
|
+
asChild: true
|
|
40
|
+
}, /* @__PURE__ */ React.createElement(Button, {
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
classNames: "pli-0 is-[--rail-action] bs-[--rail-action]",
|
|
43
|
+
"data-testid": "agent.destroy",
|
|
44
|
+
onClick: onAgentDestroy
|
|
45
|
+
}, /* @__PURE__ */ React.createElement("span", {
|
|
46
|
+
className: "sr-only"
|
|
47
|
+
}, t("destroy agent label")), /* @__PURE__ */ React.createElement(Power, {
|
|
48
|
+
className: getSize(5)
|
|
49
|
+
}))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
|
|
50
|
+
side: "bottom",
|
|
51
|
+
classNames: "z-50"
|
|
52
|
+
}, t("destroy agent label"))))), agentStatus === "created" && /* @__PURE__ */ React.createElement("p", {
|
|
53
|
+
id: "devices-panel.create-agent.description",
|
|
54
|
+
className: mx(descriptionText, "mlb-2")
|
|
55
|
+
}, t("agent requested description"))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Button, {
|
|
56
|
+
variant: "ghost",
|
|
57
|
+
classNames: "mlb-2 is-full justify-start gap-2 !pis-0 !pie-3",
|
|
58
|
+
"data-testid": agentStatus === "creatable" ? "devices-panel.create-agent" : "devices-panel.agent-error",
|
|
59
|
+
onClick: agentStatus === "creatable" ? onAgentCreate : onAgentRefresh,
|
|
60
|
+
"aria-describedby": "devices-panel.create-agent.description"
|
|
61
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
62
|
+
role: "img",
|
|
63
|
+
className: mx(getSize(8), "m-1 rounded-sm bg-input grid place-items-center")
|
|
64
|
+
}, agentStatus === "creatable" ? /* @__PURE__ */ React.createElement(Plus, {
|
|
65
|
+
weight: "light",
|
|
66
|
+
className: getSize(6)
|
|
67
|
+
}) : /* @__PURE__ */ React.createElement(ArrowsClockwise, {
|
|
68
|
+
weight: "light",
|
|
69
|
+
className: getSize(6)
|
|
70
|
+
})), /* @__PURE__ */ React.createElement("span", {
|
|
71
|
+
className: "grow font-medium text-start"
|
|
72
|
+
}, t(agentStatus === "creatable" ? "create agent label" : ""))), agentStatus === "creatable" && /* @__PURE__ */ React.createElement("div", {
|
|
73
|
+
role: "none",
|
|
74
|
+
className: "space-y-2",
|
|
75
|
+
id: "devices-panel.create-agent.description"
|
|
76
|
+
}, /* @__PURE__ */ React.createElement("p", {
|
|
77
|
+
className: descriptionText
|
|
78
|
+
}, /* @__PURE__ */ React.createElement(Trans, {
|
|
79
|
+
t,
|
|
80
|
+
i18nKey: "create agent clickwrap",
|
|
81
|
+
components: {
|
|
82
|
+
tosLink: /* @__PURE__ */ React.createElement(Link, {
|
|
83
|
+
target: "_blank",
|
|
84
|
+
rel: "noreferrer"
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
})), /* @__PURE__ */ React.createElement("p", {
|
|
88
|
+
className: descriptionText
|
|
89
|
+
}, t("create agent description")))));
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// packages/sdk/shell/src/components/Clipboard/CopyButton.tsx
|
|
93
|
+
import { Check, Copy } from "@phosphor-icons/react";
|
|
94
|
+
import React3, { useState as useState2 } from "react";
|
|
95
|
+
import { Button as Button2, Tooltip as Tooltip2, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
96
|
+
import { getSize as getSize2, mx as mx2 } from "@dxos/react-ui-theme";
|
|
97
|
+
|
|
98
|
+
// packages/sdk/shell/src/components/Clipboard/ClipboardProvider.tsx
|
|
99
|
+
import React2, { createContext, useCallback, useContext, useState } from "react";
|
|
100
|
+
var ClipboardContext = /* @__PURE__ */ createContext({
|
|
101
|
+
textValue: "",
|
|
102
|
+
setTextValue: async (_) => {
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
var useClipboardContext = () => useContext(ClipboardContext);
|
|
106
|
+
var ClipboardProvider = ({ children }) => {
|
|
107
|
+
const [textValue, setInternalTextValue] = useState("");
|
|
108
|
+
const setTextValue = useCallback(async (nextValue) => {
|
|
109
|
+
await navigator.clipboard.writeText(nextValue);
|
|
110
|
+
return setInternalTextValue(nextValue);
|
|
111
|
+
}, []);
|
|
112
|
+
return /* @__PURE__ */ React2.createElement(ClipboardContext.Provider, {
|
|
113
|
+
value: {
|
|
114
|
+
textValue,
|
|
115
|
+
setTextValue
|
|
116
|
+
}
|
|
117
|
+
}, children);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// packages/sdk/shell/src/components/Clipboard/CopyButton.tsx
|
|
121
|
+
var inactiveLabelStyles = "invisible bs-px -mbe-px overflow-hidden";
|
|
122
|
+
var CopyButton = ({ value, classNames, iconProps: iconProps2, ...props }) => {
|
|
123
|
+
const { t } = useTranslation2("os");
|
|
124
|
+
const { textValue, setTextValue } = useClipboardContext();
|
|
125
|
+
const isCopied = textValue === value;
|
|
126
|
+
return /* @__PURE__ */ React3.createElement(Button2, {
|
|
127
|
+
...props,
|
|
128
|
+
classNames: [
|
|
129
|
+
"inline-flex flex-col justify-center",
|
|
130
|
+
classNames
|
|
131
|
+
],
|
|
132
|
+
onClick: () => setTextValue(value),
|
|
133
|
+
"data-testid": "copy-invitation"
|
|
134
|
+
}, /* @__PURE__ */ React3.createElement("div", {
|
|
135
|
+
role: "none",
|
|
136
|
+
className: mx2("flex gap-1 items-center", isCopied && inactiveLabelStyles)
|
|
137
|
+
}, /* @__PURE__ */ React3.createElement("span", {
|
|
138
|
+
className: "pli-1"
|
|
139
|
+
}, t("copy invitation code label")), /* @__PURE__ */ React3.createElement(Copy, {
|
|
140
|
+
className: getSize2(5),
|
|
141
|
+
...iconProps2
|
|
142
|
+
})), /* @__PURE__ */ React3.createElement("div", {
|
|
143
|
+
role: "none",
|
|
144
|
+
className: mx2("flex gap-1 items-center", !isCopied && inactiveLabelStyles)
|
|
145
|
+
}, /* @__PURE__ */ React3.createElement("span", {
|
|
146
|
+
className: "pli-1"
|
|
147
|
+
}, t("copy success label")), /* @__PURE__ */ React3.createElement(Check, {
|
|
148
|
+
className: getSize2(5),
|
|
149
|
+
...iconProps2
|
|
150
|
+
})));
|
|
151
|
+
};
|
|
152
|
+
var CopyButtonIconOnly = ({ value, classNames, iconProps: iconProps2, variant, ...props }) => {
|
|
153
|
+
const { t } = useTranslation2("os");
|
|
154
|
+
const { textValue, setTextValue } = useClipboardContext();
|
|
155
|
+
const isCopied = textValue === value;
|
|
156
|
+
const label = isCopied ? t("copy success label") : t("copy invitation code label");
|
|
157
|
+
const [open, setOpen] = useState2(false);
|
|
158
|
+
return /* @__PURE__ */ React3.createElement(Tooltip2.Root, {
|
|
159
|
+
delayDuration: 1500,
|
|
160
|
+
open,
|
|
161
|
+
onOpenChange: setOpen
|
|
162
|
+
}, /* @__PURE__ */ React3.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip2.Content, {
|
|
163
|
+
side: "bottom",
|
|
164
|
+
sideOffset: 12,
|
|
165
|
+
classNames: "z-30"
|
|
166
|
+
}, /* @__PURE__ */ React3.createElement("span", null, label), /* @__PURE__ */ React3.createElement(Tooltip2.Arrow, null))), /* @__PURE__ */ React3.createElement(Tooltip2.Trigger, {
|
|
167
|
+
"aria-label": label,
|
|
168
|
+
...props,
|
|
169
|
+
onClick: () => setTextValue(value).then(() => setOpen(true)),
|
|
170
|
+
"data-testid": "copy-invitation",
|
|
171
|
+
asChild: true
|
|
172
|
+
}, /* @__PURE__ */ React3.createElement(Button2, {
|
|
173
|
+
variant,
|
|
174
|
+
classNames: [
|
|
175
|
+
"inline-flex flex-col justify-center",
|
|
176
|
+
classNames
|
|
177
|
+
]
|
|
178
|
+
}, /* @__PURE__ */ React3.createElement(Copy, {
|
|
179
|
+
className: getSize2(5),
|
|
180
|
+
...iconProps2
|
|
181
|
+
}))));
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// packages/sdk/shell/src/components/CompoundButton/CompoundButton.tsx
|
|
185
|
+
import React4 from "react";
|
|
186
|
+
import { useId, useThemeContext, useElevationContext } from "@dxos/react-ui";
|
|
187
|
+
import { descriptionText as descriptionText2, descriptionTextPrimary, mx as mx3 } from "@dxos/react-ui-theme";
|
|
188
|
+
var CompoundButton = ({ children, description, before, after, variant = "default", elevation: propsElevation, slots = {}, ...buttonProps }) => {
|
|
189
|
+
const labelId = useId("compoundButton-label");
|
|
190
|
+
const descriptionId = useId("compoundButton-description");
|
|
191
|
+
const { tx } = useThemeContext();
|
|
192
|
+
const elevation = useElevationContext(propsElevation);
|
|
193
|
+
const styleProps = {
|
|
194
|
+
...buttonProps,
|
|
195
|
+
variant,
|
|
196
|
+
elevation,
|
|
197
|
+
textWrap: true
|
|
198
|
+
};
|
|
199
|
+
const buttonClassName = tx("button.root", "button button--compound", styleProps, "flex items-center gap-4 plb-2.5", slots.root?.className);
|
|
200
|
+
return /* @__PURE__ */ React4.createElement("button", {
|
|
201
|
+
...buttonProps,
|
|
202
|
+
...slots.root,
|
|
203
|
+
className: buttonClassName,
|
|
204
|
+
"aria-labelledby": labelId,
|
|
205
|
+
...description && {
|
|
206
|
+
"aria-describedby": descriptionId
|
|
207
|
+
}
|
|
208
|
+
}, before && /* @__PURE__ */ React4.createElement("div", {
|
|
209
|
+
role: "none",
|
|
210
|
+
className: "grow-0"
|
|
211
|
+
}, before), /* @__PURE__ */ React4.createElement("div", {
|
|
212
|
+
role: "none",
|
|
213
|
+
...slots.middle,
|
|
214
|
+
className: mx3("grow whitespace-normal flex flex-col gap-1 text-left", slots.middle?.className)
|
|
215
|
+
}, /* @__PURE__ */ React4.createElement("p", {
|
|
216
|
+
...slots.label,
|
|
217
|
+
id: labelId,
|
|
218
|
+
className: mx3(slots.label?.className)
|
|
219
|
+
}, children), description && /* @__PURE__ */ React4.createElement("p", {
|
|
220
|
+
id: descriptionId,
|
|
221
|
+
...slots.description,
|
|
222
|
+
className: mx3("text-xs mbe-1 font-normal", variant === "primary" ? descriptionTextPrimary : descriptionText2, slots.description?.className)
|
|
223
|
+
}, description)), after && /* @__PURE__ */ React4.createElement("div", {
|
|
224
|
+
role: "none",
|
|
225
|
+
className: "grow-0"
|
|
226
|
+
}, after));
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// packages/sdk/shell/src/components/EmojiPicker.tsx
|
|
230
|
+
import emojiData from "@emoji-mart/data";
|
|
231
|
+
import EmojiMart from "@emoji-mart/react";
|
|
232
|
+
import { ArrowCounterClockwise, CaretDown, UserCircle } from "@phosphor-icons/react";
|
|
233
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
234
|
+
import React5, { useRef, useState as useState3 } from "react";
|
|
235
|
+
import { Button as Button3, Popover, Toolbar, Tooltip as Tooltip3, useMediaQuery, useThemeContext as useThemeContext2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
236
|
+
import { getSize as getSize3 } from "@dxos/react-ui-theme";
|
|
237
|
+
var EmojiPickerToolbarButton = ({ disabled, defaultEmoji, emoji, onChangeEmoji, classNames }) => {
|
|
238
|
+
const { t } = useTranslation3("os");
|
|
239
|
+
const { themeMode } = useThemeContext2();
|
|
240
|
+
const [_emojiValue, setEmojiValue] = useControllableState({
|
|
241
|
+
prop: emoji,
|
|
242
|
+
onChange: onChangeEmoji,
|
|
243
|
+
defaultProp: defaultEmoji
|
|
244
|
+
});
|
|
245
|
+
const [emojiPickerOpen, setEmojiPickerOpen] = useState3(false);
|
|
246
|
+
const suppressNextTooltip = useRef(false);
|
|
247
|
+
const [triggerTooltipOpen, setTriggerTooltipOpen] = useState3(false);
|
|
248
|
+
return /* @__PURE__ */ React5.createElement(Tooltip3.Root, {
|
|
249
|
+
open: triggerTooltipOpen,
|
|
250
|
+
onOpenChange: (nextOpen) => {
|
|
251
|
+
if (suppressNextTooltip.current) {
|
|
252
|
+
setTriggerTooltipOpen(false);
|
|
253
|
+
suppressNextTooltip.current = false;
|
|
254
|
+
} else {
|
|
255
|
+
setTriggerTooltipOpen(nextOpen);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}, /* @__PURE__ */ React5.createElement(Popover.Root, {
|
|
259
|
+
open: emojiPickerOpen,
|
|
260
|
+
onOpenChange: (nextOpen) => {
|
|
261
|
+
setEmojiPickerOpen(nextOpen);
|
|
262
|
+
suppressNextTooltip.current = true;
|
|
263
|
+
}
|
|
264
|
+
}, /* @__PURE__ */ React5.createElement(Tooltip3.Trigger, {
|
|
265
|
+
asChild: true
|
|
266
|
+
}, /* @__PURE__ */ React5.createElement(Popover.Trigger, {
|
|
267
|
+
asChild: true
|
|
268
|
+
}, /* @__PURE__ */ React5.createElement(Toolbar.Button, {
|
|
269
|
+
classNames: [
|
|
270
|
+
"gap-2 text-2xl plb-1",
|
|
271
|
+
classNames
|
|
272
|
+
],
|
|
273
|
+
disabled
|
|
274
|
+
}, /* @__PURE__ */ React5.createElement("span", {
|
|
275
|
+
className: "sr-only"
|
|
276
|
+
}, t("select emoji label")), /* @__PURE__ */ React5.createElement(UserCircle, {
|
|
277
|
+
className: getSize3(5)
|
|
278
|
+
})))), /* @__PURE__ */ React5.createElement(Tooltip3.Portal, null, /* @__PURE__ */ React5.createElement(Tooltip3.Content, {
|
|
279
|
+
side: "bottom",
|
|
280
|
+
classNames: "z-50"
|
|
281
|
+
}, t("select emoji label"), /* @__PURE__ */ React5.createElement(Tooltip3.Arrow, null))), /* @__PURE__ */ React5.createElement(Popover.Content, {
|
|
282
|
+
side: "bottom",
|
|
283
|
+
onKeyDownCapture: (event) => {
|
|
284
|
+
if (event.key === "Escape") {
|
|
285
|
+
event.stopPropagation();
|
|
286
|
+
setEmojiPickerOpen(false);
|
|
287
|
+
suppressNextTooltip.current = true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}, /* @__PURE__ */ React5.createElement(EmojiMart, {
|
|
291
|
+
data: emojiData,
|
|
292
|
+
onEmojiSelect: ({ native }) => {
|
|
293
|
+
if (native) {
|
|
294
|
+
setEmojiValue(native);
|
|
295
|
+
setEmojiPickerOpen(false);
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
autoFocus: true,
|
|
299
|
+
maxFrequentRows: 0,
|
|
300
|
+
noCountryFlags: true,
|
|
301
|
+
theme: themeMode
|
|
302
|
+
}), /* @__PURE__ */ React5.createElement(Popover.Arrow, null))));
|
|
303
|
+
};
|
|
304
|
+
var EmojiPickerBlock = ({ disabled, defaultEmoji, emoji, onChangeEmoji, onClickClear }) => {
|
|
305
|
+
const { t } = useTranslation3("os");
|
|
306
|
+
const [isMd] = useMediaQuery("md", {
|
|
307
|
+
ssr: false
|
|
308
|
+
});
|
|
309
|
+
const [emojiValue, setEmojiValue] = useControllableState({
|
|
310
|
+
prop: emoji,
|
|
311
|
+
onChange: onChangeEmoji,
|
|
312
|
+
defaultProp: defaultEmoji
|
|
313
|
+
});
|
|
314
|
+
const [emojiPickerOpen, setEmojiPickerOpen] = useState3(false);
|
|
315
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Popover.Root, {
|
|
316
|
+
open: emojiPickerOpen,
|
|
317
|
+
onOpenChange: setEmojiPickerOpen
|
|
318
|
+
}, /* @__PURE__ */ React5.createElement(Popover.Trigger, {
|
|
319
|
+
asChild: true
|
|
320
|
+
}, /* @__PURE__ */ React5.createElement(Button3, {
|
|
321
|
+
variant: "ghost",
|
|
322
|
+
classNames: "gap-2 text-2xl plb-1",
|
|
323
|
+
disabled
|
|
324
|
+
}, /* @__PURE__ */ React5.createElement("span", {
|
|
325
|
+
className: "sr-only"
|
|
326
|
+
}, t("select emoji label")), /* @__PURE__ */ React5.createElement("span", {
|
|
327
|
+
className: "grow pis-14"
|
|
328
|
+
}, emojiValue), /* @__PURE__ */ React5.createElement(CaretDown, {
|
|
329
|
+
className: getSize3(4)
|
|
330
|
+
}))), /* @__PURE__ */ React5.createElement(Popover.Content, {
|
|
331
|
+
side: "right",
|
|
332
|
+
sideOffset: isMd ? 0 : -310,
|
|
333
|
+
onKeyDownCapture: (event) => {
|
|
334
|
+
if (event.key === "Escape") {
|
|
335
|
+
event.stopPropagation();
|
|
336
|
+
setEmojiPickerOpen(false);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}, /* @__PURE__ */ React5.createElement(EmojiMart, {
|
|
340
|
+
data: emojiData,
|
|
341
|
+
onEmojiSelect: ({ native }) => {
|
|
342
|
+
if (native) {
|
|
343
|
+
setEmojiValue(native);
|
|
344
|
+
setEmojiPickerOpen(false);
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
autoFocus: true,
|
|
348
|
+
maxFrequentRows: 0,
|
|
349
|
+
noCountryFlags: true
|
|
350
|
+
}), /* @__PURE__ */ React5.createElement(Popover.Arrow, null))), /* @__PURE__ */ React5.createElement(Tooltip3.Root, null, /* @__PURE__ */ React5.createElement(Tooltip3.Trigger, {
|
|
351
|
+
asChild: true
|
|
352
|
+
}, /* @__PURE__ */ React5.createElement(Button3, {
|
|
353
|
+
variant: "ghost",
|
|
354
|
+
onClick: onClickClear,
|
|
355
|
+
disabled
|
|
356
|
+
}, /* @__PURE__ */ React5.createElement("span", {
|
|
357
|
+
className: "sr-only"
|
|
358
|
+
}, t("clear label")), /* @__PURE__ */ React5.createElement(ArrowCounterClockwise, null))), /* @__PURE__ */ React5.createElement(Tooltip3.Portal, null, /* @__PURE__ */ React5.createElement(Tooltip3.Content, {
|
|
359
|
+
style: {
|
|
360
|
+
zIndex: 70
|
|
361
|
+
},
|
|
362
|
+
side: "right"
|
|
363
|
+
}, t("clear label"), /* @__PURE__ */ React5.createElement(Tooltip3.Arrow, null)))));
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// packages/sdk/shell/src/components/HuePicker.tsx
|
|
367
|
+
import { ArrowCounterClockwise as ArrowCounterClockwise2, CaretDown as CaretDown2, Check as Check2, Palette } from "@phosphor-icons/react";
|
|
368
|
+
import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
|
|
369
|
+
import React6, { useRef as useRef2, useState as useState4 } from "react";
|
|
370
|
+
import { Button as Button4, DropdownMenu, Toolbar as Toolbar2, Tooltip as Tooltip4, useThemeContext as useThemeContext3, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
371
|
+
import { getSize as getSize4, hueTokenThemes, mx as mx4 } from "@dxos/react-ui-theme";
|
|
372
|
+
var HuePreview = ({ hue }) => {
|
|
373
|
+
const { tx } = useThemeContext3();
|
|
374
|
+
const size = 20;
|
|
375
|
+
return /* @__PURE__ */ React6.createElement("svg", {
|
|
376
|
+
width: size,
|
|
377
|
+
height: size,
|
|
378
|
+
viewBox: `0 0 ${size} ${size}`
|
|
379
|
+
}, /* @__PURE__ */ React6.createElement("rect", {
|
|
380
|
+
x: 0,
|
|
381
|
+
y: 0,
|
|
382
|
+
width: size,
|
|
383
|
+
height: size,
|
|
384
|
+
className: tx("hue.fill", "select--hue__preview", {
|
|
385
|
+
hue
|
|
386
|
+
})
|
|
387
|
+
}));
|
|
388
|
+
};
|
|
389
|
+
var hueTokens = Object.keys(hueTokenThemes).slice(0, 16);
|
|
390
|
+
var HuePickerToolbarButton = ({ disabled, hue, onChangeHue, classNames, defaultHue }) => {
|
|
391
|
+
const { t } = useTranslation4("os");
|
|
392
|
+
const [hueValue, setHueValue] = useControllableState2({
|
|
393
|
+
prop: hue,
|
|
394
|
+
onChange: onChangeHue,
|
|
395
|
+
defaultProp: defaultHue
|
|
396
|
+
});
|
|
397
|
+
const [huePickerOpen, setHuePickerOpen] = useState4(false);
|
|
398
|
+
const suppressNextTooltip = useRef2(false);
|
|
399
|
+
const [triggerTooltipOpen, setTriggerTooltipOpen] = useState4(false);
|
|
400
|
+
return /* @__PURE__ */ React6.createElement(Tooltip4.Root, {
|
|
401
|
+
open: triggerTooltipOpen,
|
|
402
|
+
onOpenChange: (nextOpen) => {
|
|
403
|
+
if (suppressNextTooltip.current) {
|
|
404
|
+
setTriggerTooltipOpen(false);
|
|
405
|
+
suppressNextTooltip.current = false;
|
|
406
|
+
} else {
|
|
407
|
+
setTriggerTooltipOpen(nextOpen);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu.Root, {
|
|
411
|
+
modal: false,
|
|
412
|
+
open: huePickerOpen,
|
|
413
|
+
onOpenChange: (nextOpen) => {
|
|
414
|
+
setHuePickerOpen(nextOpen);
|
|
415
|
+
suppressNextTooltip.current = true;
|
|
416
|
+
}
|
|
417
|
+
}, /* @__PURE__ */ React6.createElement(Tooltip4.Trigger, {
|
|
418
|
+
asChild: true
|
|
419
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu.Trigger, {
|
|
420
|
+
asChild: true
|
|
421
|
+
}, /* @__PURE__ */ React6.createElement(Toolbar2.Button, {
|
|
422
|
+
classNames: mx4("gap-2 plb-1", classNames),
|
|
423
|
+
disabled
|
|
424
|
+
}, /* @__PURE__ */ React6.createElement("span", {
|
|
425
|
+
className: "sr-only"
|
|
426
|
+
}, t("select hue label")), /* @__PURE__ */ React6.createElement(Palette, {
|
|
427
|
+
className: getSize4(5)
|
|
428
|
+
})))), /* @__PURE__ */ React6.createElement(Tooltip4.Portal, null, /* @__PURE__ */ React6.createElement(Tooltip4.Content, {
|
|
429
|
+
side: "bottom",
|
|
430
|
+
classNames: "z-50"
|
|
431
|
+
}, t("select hue label"), /* @__PURE__ */ React6.createElement(Tooltip4.Arrow, null))), /* @__PURE__ */ React6.createElement(DropdownMenu.Content, {
|
|
432
|
+
side: "bottom",
|
|
433
|
+
classNames: "!w-40"
|
|
434
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu.Viewport, {
|
|
435
|
+
classNames: "grid grid-cols-4"
|
|
436
|
+
}, hueTokens.map((hue2) => {
|
|
437
|
+
return /* @__PURE__ */ React6.createElement(DropdownMenu.CheckboxItem, {
|
|
438
|
+
key: hue2,
|
|
439
|
+
checked: hue2 === hueValue,
|
|
440
|
+
onCheckedChange: () => setHueValue(hue2),
|
|
441
|
+
classNames: "px-0 py-2 items-center justify-center"
|
|
442
|
+
}, /* @__PURE__ */ React6.createElement(HuePreview, {
|
|
443
|
+
hue: hue2
|
|
444
|
+
}));
|
|
445
|
+
})))));
|
|
446
|
+
};
|
|
447
|
+
var HuePickerBlock = ({ disabled, hue, onChangeHue, defaultHue, onClickClear }) => {
|
|
448
|
+
const { t } = useTranslation4("os");
|
|
449
|
+
const [hueValue, setHueValue] = useControllableState2({
|
|
450
|
+
prop: hue,
|
|
451
|
+
onChange: onChangeHue,
|
|
452
|
+
defaultProp: defaultHue
|
|
453
|
+
});
|
|
454
|
+
return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(DropdownMenu.Root, {
|
|
455
|
+
modal: false
|
|
456
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu.Trigger, {
|
|
457
|
+
asChild: true
|
|
458
|
+
}, /* @__PURE__ */ React6.createElement(Button4, {
|
|
459
|
+
variant: "ghost",
|
|
460
|
+
classNames: "gap-2 plb-1",
|
|
461
|
+
disabled
|
|
462
|
+
}, /* @__PURE__ */ React6.createElement("span", {
|
|
463
|
+
className: "sr-only"
|
|
464
|
+
}, t("select hue label")), /* @__PURE__ */ React6.createElement("div", {
|
|
465
|
+
role: "none",
|
|
466
|
+
className: "pis-14 grow flex items-center justify-center gap-2"
|
|
467
|
+
}, /* @__PURE__ */ React6.createElement(HuePreview, {
|
|
468
|
+
hue: hueValue
|
|
469
|
+
}), /* @__PURE__ */ React6.createElement("span", null, t(`${hueValue} label`))), /* @__PURE__ */ React6.createElement(CaretDown2, {
|
|
470
|
+
className: getSize4(4)
|
|
471
|
+
}))), /* @__PURE__ */ React6.createElement(DropdownMenu.Content, {
|
|
472
|
+
side: "right"
|
|
473
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu.Viewport, null, Object.keys(hueTokenThemes).map((hue2) => {
|
|
474
|
+
return /* @__PURE__ */ React6.createElement(DropdownMenu.CheckboxItem, {
|
|
475
|
+
key: hue2,
|
|
476
|
+
checked: hue2 === hueValue,
|
|
477
|
+
onCheckedChange: () => setHueValue(hue2)
|
|
478
|
+
}, /* @__PURE__ */ React6.createElement(HuePreview, {
|
|
479
|
+
hue: hue2
|
|
480
|
+
}), /* @__PURE__ */ React6.createElement("span", {
|
|
481
|
+
className: "grow"
|
|
482
|
+
}, t(`${hue2} label`)), /* @__PURE__ */ React6.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React6.createElement(Check2, null)));
|
|
483
|
+
})), /* @__PURE__ */ React6.createElement(DropdownMenu.Arrow, null))), /* @__PURE__ */ React6.createElement(Tooltip4.Root, null, /* @__PURE__ */ React6.createElement(Tooltip4.Trigger, {
|
|
484
|
+
asChild: true
|
|
485
|
+
}, /* @__PURE__ */ React6.createElement(Button4, {
|
|
486
|
+
variant: "ghost",
|
|
487
|
+
onClick: onClickClear,
|
|
488
|
+
disabled
|
|
489
|
+
}, /* @__PURE__ */ React6.createElement("span", {
|
|
490
|
+
className: "sr-only"
|
|
491
|
+
}, t("clear label")), /* @__PURE__ */ React6.createElement(ArrowCounterClockwise2, null))), /* @__PURE__ */ React6.createElement(Tooltip4.Portal, null, /* @__PURE__ */ React6.createElement(Tooltip4.Content, {
|
|
492
|
+
style: {
|
|
493
|
+
zIndex: 70
|
|
494
|
+
},
|
|
495
|
+
side: "right"
|
|
496
|
+
}, t("clear label"), /* @__PURE__ */ React6.createElement(Tooltip4.Arrow, null)))));
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
// packages/sdk/shell/src/components/IdentityList/IdentityListItem.tsx
|
|
500
|
+
import React7, { forwardRef } from "react";
|
|
501
|
+
import { generateName } from "@dxos/display-name";
|
|
502
|
+
import { SpaceMember } from "@dxos/react-client/echo";
|
|
503
|
+
import { ListItem, Avatar as Avatar2, useId as useId2 } from "@dxos/react-ui";
|
|
504
|
+
import { mx as mx5 } from "@dxos/react-ui-theme";
|
|
505
|
+
import { keyToFallback } from "@dxos/util";
|
|
506
|
+
var IdentityListItem = /* @__PURE__ */ forwardRef(({ identity, presence, onClick, classNames, ...props }, forwardedRef) => {
|
|
507
|
+
const fallbackValue = keyToFallback(identity.identityKey);
|
|
508
|
+
const labelId = useId2("identityListItem__label");
|
|
509
|
+
const displayName = identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
|
|
510
|
+
return /* @__PURE__ */ React7.createElement(ListItem.Root, {
|
|
511
|
+
...props,
|
|
512
|
+
classNames: mx5("flex gap-2 pis-3 pie-1 items-center", onClick && "cursor-pointer", classNames),
|
|
513
|
+
onClick: () => onClick?.(),
|
|
514
|
+
"data-testid": "identity-list-item",
|
|
515
|
+
labelId,
|
|
516
|
+
ref: forwardedRef
|
|
517
|
+
}, /* @__PURE__ */ React7.createElement(Avatar2.Root, {
|
|
518
|
+
status: presence === SpaceMember.PresenceState.ONLINE ? "active" : "inactive",
|
|
519
|
+
labelId,
|
|
520
|
+
hue: identity.profile?.data?.hue || fallbackValue.hue
|
|
521
|
+
}, /* @__PURE__ */ React7.createElement(Avatar2.Frame, {
|
|
522
|
+
classNames: "place-self-center"
|
|
523
|
+
}, /* @__PURE__ */ React7.createElement(Avatar2.Fallback, {
|
|
524
|
+
text: identity.profile?.data?.emoji || fallbackValue.emoji
|
|
525
|
+
})), /* @__PURE__ */ React7.createElement(Avatar2.Label, {
|
|
526
|
+
classNames: "text-sm truncate pli-2"
|
|
527
|
+
}, displayName)));
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// packages/sdk/shell/src/components/IdentityList/SpaceMemberList.tsx
|
|
531
|
+
import React8, { useMemo } from "react";
|
|
532
|
+
import { useClient } from "@dxos/react-client";
|
|
533
|
+
import { useMembers } from "@dxos/react-client/echo";
|
|
534
|
+
import { useTranslation as useTranslation5, List } from "@dxos/react-ui";
|
|
535
|
+
import { descriptionText as descriptionText3, mx as mx6 } from "@dxos/react-ui-theme";
|
|
536
|
+
var SpaceMemberList = ({ spaceKey, includeSelf, onSelect }) => {
|
|
537
|
+
const client = useClient();
|
|
538
|
+
const allUnsortedMembers = useMembers(spaceKey);
|
|
539
|
+
const members = useMemo(() => includeSelf ? allUnsortedMembers.sort((member) => member.identity.identityKey.equals(client.halo.identity.get().identityKey) ? -1 : 1) : allUnsortedMembers.filter((member) => !member.identity.identityKey.equals(client.halo.identity.get().identityKey)), [
|
|
540
|
+
allUnsortedMembers
|
|
541
|
+
]);
|
|
542
|
+
return /* @__PURE__ */ React8.createElement(SpaceMemberListImpl, {
|
|
543
|
+
members,
|
|
544
|
+
onSelect
|
|
545
|
+
});
|
|
546
|
+
};
|
|
547
|
+
var SpaceMemberListImpl = ({ members, onSelect }) => {
|
|
548
|
+
const { t } = useTranslation5("os");
|
|
549
|
+
const visibleMembers = members.filter((member) => member.identity);
|
|
550
|
+
return visibleMembers.length > 0 ? /* @__PURE__ */ React8.createElement(List, {
|
|
551
|
+
classNames: "flex flex-col gap-2",
|
|
552
|
+
"data-testid": "space-members-list"
|
|
553
|
+
}, visibleMembers.map((member) => {
|
|
554
|
+
return /* @__PURE__ */ React8.createElement(IdentityListItem, {
|
|
555
|
+
key: member.identity.identityKey.toHex(),
|
|
556
|
+
identity: member.identity,
|
|
557
|
+
presence: member.presence,
|
|
558
|
+
onClick: onSelect && (() => onSelect(member))
|
|
559
|
+
});
|
|
560
|
+
})) : /* @__PURE__ */ React8.createElement("div", {
|
|
561
|
+
role: "none",
|
|
562
|
+
className: "grow flex items-center p-2"
|
|
563
|
+
}, /* @__PURE__ */ React8.createElement("p", {
|
|
564
|
+
className: mx6(descriptionText3, "text-center is-full mlb-2")
|
|
565
|
+
}, t("empty space members message")));
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// packages/sdk/shell/src/components/DeviceList/DeviceList.tsx
|
|
569
|
+
import { CaretRight, Plus as Plus2 } from "@phosphor-icons/react";
|
|
570
|
+
import React10 from "react";
|
|
571
|
+
import { Button as Button6, List as List2, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
572
|
+
import { descriptionText as descriptionText4, getSize as getSize6, mx as mx7 } from "@dxos/react-ui-theme";
|
|
573
|
+
|
|
574
|
+
// packages/sdk/shell/src/components/DeviceList/DeviceListItem.tsx
|
|
575
|
+
import { Compass, Desktop, DeviceMobile, Devices, DotsThree, ShareFat, Power as Power2, Robot, Database as Database2, FirstAidKit } from "@phosphor-icons/react";
|
|
576
|
+
import React9, { forwardRef as forwardRef2 } from "react";
|
|
577
|
+
import { generateName as generateName2 } from "@dxos/display-name";
|
|
578
|
+
import { Device, DeviceType, DeviceKind } from "@dxos/react-client/halo";
|
|
579
|
+
import { ConnectionState } from "@dxos/react-client/mesh";
|
|
580
|
+
import { ListItem as ListItem2, Avatar as Avatar3, useId as useId3, Tag, useTranslation as useTranslation6, DropdownMenu as DropdownMenu2, Button as Button5, Tooltip as Tooltip5 } from "@dxos/react-ui";
|
|
581
|
+
import { getSize as getSize5 } from "@dxos/react-ui-theme";
|
|
582
|
+
import { keyToFallback as keyToFallback2 } from "@dxos/util";
|
|
583
|
+
var iconProps = {
|
|
584
|
+
weight: "duotone",
|
|
585
|
+
width: 24,
|
|
586
|
+
height: 24,
|
|
587
|
+
x: 8,
|
|
588
|
+
y: 8
|
|
589
|
+
};
|
|
590
|
+
var DeviceListItem = /* @__PURE__ */ forwardRef2(({ device, onClickAdd, onClickEdit, onClickReset, onClickRecover, onClickJoinExisting, classNames, connectionState, onAgentDestroy, ...props }, forwardedRef) => {
|
|
591
|
+
const { t } = useTranslation6("os");
|
|
592
|
+
const fallbackValue = keyToFallback2(device.deviceKey);
|
|
593
|
+
const labelId = useId3("identityListItem__label");
|
|
594
|
+
const displayName = device.profile ? t("device name placeholder", {
|
|
595
|
+
os: device.profile.os,
|
|
596
|
+
platform: device.profile.platform
|
|
597
|
+
}) : generateName2(device.deviceKey.toHex());
|
|
598
|
+
const isCurrent = device.kind === DeviceKind.CURRENT;
|
|
599
|
+
return /* @__PURE__ */ React9.createElement(ListItem2.Root, {
|
|
600
|
+
...props,
|
|
601
|
+
classNames: [
|
|
602
|
+
"flex gap-2 items-center mlb-2",
|
|
603
|
+
classNames
|
|
604
|
+
],
|
|
605
|
+
"data-testid": `device-list-item${isCurrent ? "-current" : ""}`,
|
|
606
|
+
labelId,
|
|
607
|
+
ref: forwardedRef
|
|
608
|
+
}, /* @__PURE__ */ React9.createElement(Avatar3.Root, {
|
|
609
|
+
status: isCurrent && connectionState === ConnectionState.OFFLINE ? "error" : device.presence === Device.PresenceState.ONLINE ? "active" : "inactive",
|
|
610
|
+
labelId,
|
|
611
|
+
hue: fallbackValue.hue,
|
|
612
|
+
variant: "square"
|
|
613
|
+
}, /* @__PURE__ */ React9.createElement(Avatar3.Frame, {
|
|
614
|
+
classNames: "place-self-center"
|
|
615
|
+
}, device.profile?.type ? device.profile.type === DeviceType.AGENT_MANAGED ? /* @__PURE__ */ React9.createElement(Database2, iconProps) : device.profile.type === DeviceType.BROWSER ? /* @__PURE__ */ React9.createElement(Compass, iconProps) : device.profile.type === DeviceType.NATIVE ? /* @__PURE__ */ React9.createElement(Desktop, iconProps) : [
|
|
616
|
+
DeviceType.AGENT,
|
|
617
|
+
DeviceType.AGENT_MANAGED
|
|
618
|
+
].includes(device.profile.type) ? /* @__PURE__ */ React9.createElement(Robot, iconProps) : device.profile.type === DeviceType.MOBILE ? /* @__PURE__ */ React9.createElement(DeviceMobile, iconProps) : /* @__PURE__ */ React9.createElement(Devices, iconProps) : /* @__PURE__ */ React9.createElement(Avatar3.Fallback, {
|
|
619
|
+
text: fallbackValue.emoji
|
|
620
|
+
})), /* @__PURE__ */ React9.createElement(Avatar3.Label, {
|
|
621
|
+
classNames: "flex-1 text-sm truncate"
|
|
622
|
+
}, displayName), isCurrent && /* @__PURE__ */ React9.createElement(Tag, {
|
|
623
|
+
color: "primary"
|
|
624
|
+
}, t("current device tag label")), device.profile?.type === DeviceType.AGENT_MANAGED ? /* @__PURE__ */ React9.createElement(Tooltip5.Root, null, /* @__PURE__ */ React9.createElement(Tooltip5.Trigger, {
|
|
625
|
+
asChild: true
|
|
626
|
+
}, /* @__PURE__ */ React9.createElement(Button5, {
|
|
627
|
+
variant: "ghost",
|
|
628
|
+
classNames: "pli-0 is-[--rail-action] bs-[--rail-action]",
|
|
629
|
+
"data-testid": "agent.destroy",
|
|
630
|
+
onClick: onAgentDestroy
|
|
631
|
+
}, /* @__PURE__ */ React9.createElement("span", {
|
|
632
|
+
className: "sr-only"
|
|
633
|
+
}, t("destroy agent label")), /* @__PURE__ */ React9.createElement(Power2, {
|
|
634
|
+
className: getSize5(5)
|
|
635
|
+
}))), /* @__PURE__ */ React9.createElement(Tooltip5.Portal, null, /* @__PURE__ */ React9.createElement(Tooltip5.Content, {
|
|
636
|
+
side: "bottom",
|
|
637
|
+
classNames: "z-50"
|
|
638
|
+
}, t("destroy agent label")))) : device.kind === DeviceKind.CURRENT && /* @__PURE__ */ React9.createElement(DropdownMenu2.Root, null, /* @__PURE__ */ React9.createElement(DropdownMenu2.Trigger, {
|
|
639
|
+
asChild: true
|
|
640
|
+
}, /* @__PURE__ */ React9.createElement(Button5, {
|
|
641
|
+
variant: "ghost",
|
|
642
|
+
classNames: "pli-0 is-[--rail-action] bs-[--rail-action]",
|
|
643
|
+
"data-testid": `device-list-item${isCurrent ? "-current" : ""}.options`
|
|
644
|
+
}, /* @__PURE__ */ React9.createElement("span", {
|
|
645
|
+
className: "sr-only"
|
|
646
|
+
}, t("more options label")), /* @__PURE__ */ React9.createElement(DotsThree, {
|
|
647
|
+
className: getSize5(5)
|
|
648
|
+
}))), /* @__PURE__ */ React9.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React9.createElement(DropdownMenu2.Viewport, null, /* @__PURE__ */ React9.createElement(DropdownMenu2.Item, {
|
|
649
|
+
"data-testid": "device-list-item-current.join-existing",
|
|
650
|
+
onClick: onClickJoinExisting
|
|
651
|
+
}, /* @__PURE__ */ React9.createElement(ShareFat, {
|
|
652
|
+
className: getSize5(5)
|
|
653
|
+
}), t("choose join new identity label")), onClickRecover && /* @__PURE__ */ React9.createElement(DropdownMenu2.Item, {
|
|
654
|
+
"data-testid": "device-list-item-current.recover",
|
|
655
|
+
onClick: onClickRecover
|
|
656
|
+
}, /* @__PURE__ */ React9.createElement(FirstAidKit, {
|
|
657
|
+
className: getSize5(5)
|
|
658
|
+
}), t("choose recover identity label")), /* @__PURE__ */ React9.createElement(DropdownMenu2.Item, {
|
|
659
|
+
"data-testid": "device-list-item-current.reset",
|
|
660
|
+
onClick: onClickReset
|
|
661
|
+
}, /* @__PURE__ */ React9.createElement(Power2, {
|
|
662
|
+
className: getSize5(5)
|
|
663
|
+
}), t("reset device label")))))));
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// packages/sdk/shell/src/components/DeviceList/DeviceList.tsx
|
|
667
|
+
var DeviceList = ({ devices, connectionState, onClickAdd, onClickEdit, onClickReset, onClickRecover, onClickJoinExisting, onAgentDestroy }) => {
|
|
668
|
+
const { t } = useTranslation7("os");
|
|
669
|
+
return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("h2", {
|
|
670
|
+
className: mx7(descriptionText4, "text-center mbs-4")
|
|
671
|
+
}, t("devices heading")), devices.length > 0 && /* @__PURE__ */ React10.createElement(List2, null, devices.map((device) => {
|
|
672
|
+
return /* @__PURE__ */ React10.createElement(DeviceListItem, {
|
|
673
|
+
key: device.deviceKey.toHex(),
|
|
674
|
+
device,
|
|
675
|
+
onClickEdit: () => onClickEdit?.(device),
|
|
676
|
+
onClickReset,
|
|
677
|
+
onClickRecover,
|
|
678
|
+
onClickJoinExisting,
|
|
679
|
+
connectionState,
|
|
680
|
+
onAgentDestroy
|
|
681
|
+
});
|
|
682
|
+
})), /* @__PURE__ */ React10.createElement(Button6, {
|
|
683
|
+
variant: "ghost",
|
|
684
|
+
classNames: "justify-start gap-2 !pis-0 !pie-3 is-full",
|
|
685
|
+
"data-testid": "devices-panel.create-invitation",
|
|
686
|
+
onClick: onClickAdd
|
|
687
|
+
}, /* @__PURE__ */ React10.createElement("div", {
|
|
688
|
+
role: "img",
|
|
689
|
+
className: mx7(getSize6(8), "m-1 rounded-sm bg-input grid place-items-center")
|
|
690
|
+
}, /* @__PURE__ */ React10.createElement(Plus2, {
|
|
691
|
+
weight: "light",
|
|
692
|
+
className: getSize6(6)
|
|
693
|
+
})), /* @__PURE__ */ React10.createElement("span", {
|
|
694
|
+
className: "grow font-medium text-start"
|
|
695
|
+
}, t("choose add device label")), /* @__PURE__ */ React10.createElement(CaretRight, {
|
|
696
|
+
weight: "bold",
|
|
697
|
+
className: getSize6(4)
|
|
698
|
+
})));
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
// packages/sdk/shell/src/components/InvitationList/InvitationListItem.tsx
|
|
702
|
+
import { X } from "@phosphor-icons/react";
|
|
703
|
+
import { formatDistanceToNow } from "date-fns";
|
|
704
|
+
import React12, { useCallback as useCallback2 } from "react";
|
|
705
|
+
import { Invitation, useInvitationStatus } from "@dxos/react-client/invitations";
|
|
706
|
+
import { Button as Button7, ListItem as ListItem3, useTranslation as useTranslation8, Avatar as Avatar4, useThemeContext as useThemeContext4, Tooltip as Tooltip6 } from "@dxos/react-ui";
|
|
707
|
+
import { focusRing, getSize as getSize7, mx as mx9 } from "@dxos/react-ui-theme";
|
|
708
|
+
import { hexToEmoji } from "@dxos/util";
|
|
709
|
+
|
|
710
|
+
// packages/sdk/shell/src/components/AuthCode.tsx
|
|
711
|
+
import React11, { useRef as useRef3 } from "react";
|
|
712
|
+
import { mx as mx8 } from "@dxos/react-ui-theme";
|
|
713
|
+
var AuthCode = (props) => {
|
|
714
|
+
const { code, large, classNames } = props;
|
|
715
|
+
const l = code?.length ?? 0;
|
|
716
|
+
const left = code?.slice(0, l / 2);
|
|
717
|
+
const right = code?.slice(l / 2);
|
|
718
|
+
const codeRef = useRef3(null);
|
|
719
|
+
const handleClick = () => {
|
|
720
|
+
if (codeRef.current) {
|
|
721
|
+
const selection = window.getSelection();
|
|
722
|
+
selection?.removeAllRanges();
|
|
723
|
+
const range = document.createRange();
|
|
724
|
+
range.selectNodeContents(codeRef.current);
|
|
725
|
+
selection?.addRange(range);
|
|
726
|
+
}
|
|
727
|
+
void navigator.clipboard.writeText(code ?? "");
|
|
728
|
+
};
|
|
729
|
+
return /* @__PURE__ */ React11.createElement("span", {
|
|
730
|
+
className: mx8(large ? "text-6xl" : "text-2xl", "font-mono pli-2.5 rounded cursor-pointer", classNames),
|
|
731
|
+
onClick: handleClick,
|
|
732
|
+
ref: codeRef
|
|
733
|
+
}, /* @__PURE__ */ React11.createElement("span", {
|
|
734
|
+
className: "mie-[0.4em]"
|
|
735
|
+
}, left), /* @__PURE__ */ React11.createElement("span", null, right));
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
// packages/sdk/shell/src/components/InvitationList/InvitationListItem.tsx
|
|
739
|
+
var InvitationListItem = (props) => {
|
|
740
|
+
const { invitation } = props;
|
|
741
|
+
const invitationStatus = useInvitationStatus(invitation);
|
|
742
|
+
return /* @__PURE__ */ React12.createElement(InvitationListItemImpl, {
|
|
743
|
+
...props,
|
|
744
|
+
invitationStatus
|
|
745
|
+
});
|
|
746
|
+
};
|
|
747
|
+
var avatarProps = {
|
|
748
|
+
size: 10,
|
|
749
|
+
variant: "circle"
|
|
750
|
+
};
|
|
751
|
+
var AvatarStackEffect = ({ animation, status, reverseEffects }) => {
|
|
752
|
+
const { tx } = useThemeContext4();
|
|
753
|
+
return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement("span", {
|
|
754
|
+
role: "none",
|
|
755
|
+
className: mx9("absolute inline-end-auto opacity-20", reverseEffects ? "inline-start-3" : "inline-start-1", getSize7(avatarProps.size))
|
|
756
|
+
}, /* @__PURE__ */ React12.createElement("span", {
|
|
757
|
+
role: "none",
|
|
758
|
+
className: tx("avatar.ring", "avatar__ring", {
|
|
759
|
+
...avatarProps,
|
|
760
|
+
status,
|
|
761
|
+
animation
|
|
762
|
+
}),
|
|
763
|
+
style: {
|
|
764
|
+
animationDelay: "400ms"
|
|
765
|
+
}
|
|
766
|
+
})), /* @__PURE__ */ React12.createElement("span", {
|
|
767
|
+
role: "none",
|
|
768
|
+
className: mx9("absolute inline-end-auto opacity-50", reverseEffects ? "inline-start-2" : "inline-start-2", getSize7(avatarProps.size))
|
|
769
|
+
}, /* @__PURE__ */ React12.createElement("span", {
|
|
770
|
+
role: "none",
|
|
771
|
+
className: tx("avatar.ring", "avatar__ring", {
|
|
772
|
+
...avatarProps,
|
|
773
|
+
status,
|
|
774
|
+
animation
|
|
775
|
+
}),
|
|
776
|
+
style: {
|
|
777
|
+
animationDelay: "200ms"
|
|
778
|
+
}
|
|
779
|
+
})));
|
|
780
|
+
};
|
|
781
|
+
var InvitationListItemImpl = ({ invitation, invitationStatus: propsInvitationStatus, send, onClickRemove, createInvitationUrl, reverseEffects, ...props }) => {
|
|
782
|
+
const { t } = useTranslation8("os");
|
|
783
|
+
const { cancel, status: invitationStatus, invitationCode, authCode, multiUse, shareable } = propsInvitationStatus;
|
|
784
|
+
const isCancellable = !([
|
|
785
|
+
Invitation.State.ERROR,
|
|
786
|
+
Invitation.State.TIMEOUT,
|
|
787
|
+
Invitation.State.CANCELLED
|
|
788
|
+
].indexOf(invitationStatus) >= 0);
|
|
789
|
+
const showShare = shareable && (multiUse || [
|
|
790
|
+
Invitation.State.INIT,
|
|
791
|
+
Invitation.State.CONNECTING,
|
|
792
|
+
Invitation.State.CONNECTED
|
|
793
|
+
].indexOf(invitationStatus) >= 0);
|
|
794
|
+
const showAuthCode = invitationStatus === Invitation.State.READY_FOR_AUTHENTICATION;
|
|
795
|
+
const handleClickRemove = useCallback2(() => onClickRemove?.(invitation), [
|
|
796
|
+
invitation,
|
|
797
|
+
onClickRemove
|
|
798
|
+
]);
|
|
799
|
+
const invitationUrl = invitationCode && createInvitationUrl(invitationCode);
|
|
800
|
+
const invitationId = invitation?.get().invitationId;
|
|
801
|
+
const invitationHasLifetime = invitation?.get().lifetime;
|
|
802
|
+
const invitationTimeLeft = invitation?.expiry ? formatDistanceToNow(invitation?.expiry, {
|
|
803
|
+
addSuffix: true
|
|
804
|
+
}) : void 0;
|
|
805
|
+
const avatarAnimation = [
|
|
806
|
+
Invitation.State.INIT,
|
|
807
|
+
Invitation.State.CONNECTING,
|
|
808
|
+
Invitation.State.CONNECTED,
|
|
809
|
+
Invitation.State.READY_FOR_AUTHENTICATION,
|
|
810
|
+
Invitation.State.AUTHENTICATING
|
|
811
|
+
].includes(invitationStatus) ? "pulse" : "none";
|
|
812
|
+
const avatarError = [
|
|
813
|
+
Invitation.State.ERROR,
|
|
814
|
+
Invitation.State.TIMEOUT,
|
|
815
|
+
Invitation.State.CANCELLED
|
|
816
|
+
].includes(invitationStatus);
|
|
817
|
+
const avatarGreen = [
|
|
818
|
+
Invitation.State.CONNECTED,
|
|
819
|
+
Invitation.State.READY_FOR_AUTHENTICATION,
|
|
820
|
+
Invitation.State.AUTHENTICATING,
|
|
821
|
+
Invitation.State.SUCCESS
|
|
822
|
+
].includes(invitationStatus);
|
|
823
|
+
const avatarStatus = avatarError ? "error" : avatarGreen ? "active" : "inactive";
|
|
824
|
+
return /* @__PURE__ */ React12.createElement(ListItem3.Root, {
|
|
825
|
+
id: invitationCode,
|
|
826
|
+
...props,
|
|
827
|
+
classNames: [
|
|
828
|
+
"flex gap-2 pis-3 pie-1 items-center relative",
|
|
829
|
+
props.classNames
|
|
830
|
+
]
|
|
831
|
+
}, /* @__PURE__ */ React12.createElement(ListItem3.Heading, {
|
|
832
|
+
classNames: "sr-only"
|
|
833
|
+
}, t(multiUse ? "invite many list item label" : "invite one list item label")), multiUse && /* @__PURE__ */ React12.createElement(AvatarStackEffect, {
|
|
834
|
+
status: avatarStatus,
|
|
835
|
+
animation: avatarAnimation,
|
|
836
|
+
reverseEffects
|
|
837
|
+
}), /* @__PURE__ */ React12.createElement(Tooltip6.Root, null, /* @__PURE__ */ React12.createElement(Avatar4.Root, {
|
|
838
|
+
...avatarProps,
|
|
839
|
+
animation: avatarAnimation,
|
|
840
|
+
status: avatarStatus
|
|
841
|
+
}, /* @__PURE__ */ React12.createElement(Tooltip6.Trigger, {
|
|
842
|
+
asChild: true
|
|
843
|
+
}, /* @__PURE__ */ React12.createElement(Avatar4.Frame, {
|
|
844
|
+
tabIndex: 0,
|
|
845
|
+
classNames: [
|
|
846
|
+
focusRing,
|
|
847
|
+
"relative rounded-full place-self-center"
|
|
848
|
+
]
|
|
849
|
+
}, /* @__PURE__ */ React12.createElement(Avatar4.Fallback, {
|
|
850
|
+
text: hexToEmoji(invitationId)
|
|
851
|
+
})))), /* @__PURE__ */ React12.createElement(Tooltip6.Portal, null, /* @__PURE__ */ React12.createElement(Tooltip6.Content, {
|
|
852
|
+
side: "left",
|
|
853
|
+
classNames: "z-[70]"
|
|
854
|
+
}, t(multiUse ? "invite many qr label" : "invite one qr label"), /* @__PURE__ */ React12.createElement(Tooltip6.Arrow, null)))), showShare && invitationUrl ? /* @__PURE__ */ React12.createElement(Tooltip6.Root, null, /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(Tooltip6.Trigger, {
|
|
855
|
+
asChild: true
|
|
856
|
+
}, /* @__PURE__ */ React12.createElement(Button7, {
|
|
857
|
+
variant: "ghost",
|
|
858
|
+
classNames: "grow justify-start font-medium",
|
|
859
|
+
onClick: () => send({
|
|
860
|
+
type: "selectInvitation",
|
|
861
|
+
invitation
|
|
862
|
+
}),
|
|
863
|
+
"data-testid": "show-qrcode"
|
|
864
|
+
}, /* @__PURE__ */ React12.createElement("span", null, t("open share panel label")))), /* @__PURE__ */ React12.createElement(CopyButtonIconOnly, {
|
|
865
|
+
variant: "ghost",
|
|
866
|
+
value: invitationUrl
|
|
867
|
+
})), /* @__PURE__ */ React12.createElement(Tooltip6.Portal, null, /* @__PURE__ */ React12.createElement(Tooltip6.Content, {
|
|
868
|
+
side: "left",
|
|
869
|
+
classNames: "z-[70]"
|
|
870
|
+
}, invitationHasLifetime && /* @__PURE__ */ React12.createElement("span", null, "Expires ", invitationTimeLeft)))) : showAuthCode ? /* @__PURE__ */ React12.createElement(AuthCode, {
|
|
871
|
+
code: authCode,
|
|
872
|
+
classNames: "grow"
|
|
873
|
+
}) : invitationStatus === Invitation.State.CONNECTING ? /* @__PURE__ */ React12.createElement("span", {
|
|
874
|
+
className: "pli-2 grow text-neutral-500"
|
|
875
|
+
}, "Connecting...") : invitationStatus === Invitation.State.AUTHENTICATING ? /* @__PURE__ */ React12.createElement("span", {
|
|
876
|
+
className: "pli-2 grow text-neutral-500"
|
|
877
|
+
}, "Authenticating...") : invitationStatus === Invitation.State.ERROR || invitationStatus === Invitation.State.TIMEOUT ? /* @__PURE__ */ React12.createElement("span", {
|
|
878
|
+
className: "pli-2 grow text-neutral-500"
|
|
879
|
+
}, "Failed") : invitationStatus === Invitation.State.CANCELLED ? /* @__PURE__ */ React12.createElement("span", {
|
|
880
|
+
className: "pli-2 grow text-neutral-500"
|
|
881
|
+
}, "Cancelled") : invitationStatus === Invitation.State.SUCCESS ? /* @__PURE__ */ React12.createElement("span", {
|
|
882
|
+
className: "pli-2 grow truncate"
|
|
883
|
+
}, "User joined") : !shareable ? /* @__PURE__ */ React12.createElement("span", {
|
|
884
|
+
className: "pli-2 grow text-neutral-500"
|
|
885
|
+
}, "Pending Invitation") : /* @__PURE__ */ React12.createElement("span", {
|
|
886
|
+
className: "grow"
|
|
887
|
+
}, " "), isCancellable ? /* @__PURE__ */ React12.createElement(Button7, {
|
|
888
|
+
variant: "ghost",
|
|
889
|
+
classNames: "flex gap-1 pli-0",
|
|
890
|
+
onClick: cancel,
|
|
891
|
+
"data-testid": "cancel-invitation"
|
|
892
|
+
}, /* @__PURE__ */ React12.createElement("span", {
|
|
893
|
+
className: "sr-only"
|
|
894
|
+
}, t("cancel invitation label")), /* @__PURE__ */ React12.createElement(X, {
|
|
895
|
+
className: getSize7(4)
|
|
896
|
+
})) : /* @__PURE__ */ React12.createElement(Button7, {
|
|
897
|
+
variant: "ghost",
|
|
898
|
+
classNames: "flex gap-1 pli-0",
|
|
899
|
+
onClick: handleClickRemove,
|
|
900
|
+
"data-testid": "remove-invitation"
|
|
901
|
+
}, /* @__PURE__ */ React12.createElement("span", {
|
|
902
|
+
className: "sr-only"
|
|
903
|
+
}, t("remove invitation label")), /* @__PURE__ */ React12.createElement(X, {
|
|
904
|
+
className: getSize7(4)
|
|
905
|
+
})));
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
// packages/sdk/shell/src/components/InvitationList/InvitationListContainer.tsx
|
|
909
|
+
import React14, { useCallback as useCallback3 } from "react";
|
|
910
|
+
import { useSpace, useSpaceInvitations } from "@dxos/react-client/echo";
|
|
911
|
+
|
|
912
|
+
// packages/sdk/shell/src/components/InvitationList/InvitationList.tsx
|
|
913
|
+
import React13 from "react";
|
|
914
|
+
import { List as List3 } from "@dxos/react-ui";
|
|
915
|
+
import { mx as mx10 } from "@dxos/react-ui-theme";
|
|
916
|
+
var InvitationList = ({ invitations, send, ...invitationProps }) => {
|
|
917
|
+
const { className, InvitationListItem: Item = InvitationListItem } = invitationProps;
|
|
918
|
+
return /* @__PURE__ */ React13.createElement(List3, {
|
|
919
|
+
classNames: mx10("flex flex-col gap-2", className)
|
|
920
|
+
}, invitations.map((invitation) => {
|
|
921
|
+
const value = invitation.get().invitationId;
|
|
922
|
+
return /* @__PURE__ */ React13.createElement(Item, {
|
|
923
|
+
key: value,
|
|
924
|
+
send,
|
|
925
|
+
invitation,
|
|
926
|
+
...invitationProps
|
|
927
|
+
});
|
|
928
|
+
}));
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
// packages/sdk/shell/src/components/InvitationList/InvitationListContainer.tsx
|
|
932
|
+
var InvitationListContainer = ({ spaceKey, createInvitationUrl, send }) => {
|
|
933
|
+
const space = useSpace(spaceKey);
|
|
934
|
+
const invitations = useSpaceInvitations(spaceKey);
|
|
935
|
+
const handleClickRemove = useCallback3((invitation) => {
|
|
936
|
+
void invitation.cancel();
|
|
937
|
+
}, [
|
|
938
|
+
space
|
|
939
|
+
]);
|
|
940
|
+
return /* @__PURE__ */ React14.createElement(InvitationList, {
|
|
941
|
+
invitations,
|
|
942
|
+
onClickRemove: handleClickRemove,
|
|
943
|
+
createInvitationUrl,
|
|
944
|
+
send
|
|
945
|
+
});
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
// packages/sdk/shell/src/components/Panel/Action.tsx
|
|
949
|
+
import { CaretDown as CaretDown3, Check as Check3, Placeholder } from "@phosphor-icons/react";
|
|
950
|
+
import { useControllableState as useControllableState3 } from "@radix-ui/react-use-controllable-state";
|
|
951
|
+
import React15, { forwardRef as forwardRef3 } from "react";
|
|
952
|
+
import { Button as Button8, DropdownMenu as DropdownMenu3, useTranslation as useTranslation9 } from "@dxos/react-ui";
|
|
953
|
+
import { descriptionText as descriptionText5, getSize as getSize8, mx as mx11 } from "@dxos/react-ui-theme";
|
|
954
|
+
var defaultActions = {
|
|
955
|
+
noopAction: {
|
|
956
|
+
label: "No-op",
|
|
957
|
+
description: "",
|
|
958
|
+
icon: Placeholder,
|
|
959
|
+
onClick: () => {
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
var BifurcatedAction = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
|
|
964
|
+
const { classNames, variant, isFull = true, actions = defaultActions, activeAction: propsActiveAction, onChangeActiveAction, defaultActiveAction, ...rest } = props;
|
|
965
|
+
const [activeActionKey2 = Object.keys(actions)[0], setActiveAction] = useControllableState3({
|
|
966
|
+
prop: propsActiveAction,
|
|
967
|
+
onChange: onChangeActiveAction,
|
|
968
|
+
defaultProp: defaultActiveAction
|
|
969
|
+
});
|
|
970
|
+
const activeAction = actions[activeActionKey2] ?? {};
|
|
971
|
+
const { t } = useTranslation9("os");
|
|
972
|
+
return /* @__PURE__ */ React15.createElement("div", {
|
|
973
|
+
role: "none",
|
|
974
|
+
className: mx11("mbs-2 flex gap-px items-center", isFull && "is-full")
|
|
975
|
+
}, /* @__PURE__ */ React15.createElement(Button8, {
|
|
976
|
+
...rest,
|
|
977
|
+
classNames: [
|
|
978
|
+
"bs-11 flex-1 min-is-0 flex gap-2 rounded-ie-none",
|
|
979
|
+
classNames
|
|
980
|
+
],
|
|
981
|
+
ref: forwardedRef,
|
|
982
|
+
variant,
|
|
983
|
+
onClick: activeAction.onClick
|
|
984
|
+
}, activeAction.icon && /* @__PURE__ */ React15.createElement(activeAction.icon, {
|
|
985
|
+
className: getSize8(5)
|
|
986
|
+
}), /* @__PURE__ */ React15.createElement("span", null, activeAction.label)), /* @__PURE__ */ React15.createElement(DropdownMenu3.Root, null, /* @__PURE__ */ React15.createElement(DropdownMenu3.Trigger, {
|
|
987
|
+
asChild: true
|
|
988
|
+
}, /* @__PURE__ */ React15.createElement(Button8, {
|
|
989
|
+
classNames: [
|
|
990
|
+
"bs-11 flex-none rounded-is-none",
|
|
991
|
+
classNames
|
|
992
|
+
]
|
|
993
|
+
}, /* @__PURE__ */ React15.createElement("span", {
|
|
994
|
+
className: "sr-only"
|
|
995
|
+
}, t("invite options label")), /* @__PURE__ */ React15.createElement(CaretDown3, {
|
|
996
|
+
className: getSize8(4)
|
|
997
|
+
}))), /* @__PURE__ */ React15.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React15.createElement(DropdownMenu3.Viewport, null, Object.entries(actions).map(([id, action]) => {
|
|
998
|
+
return /* @__PURE__ */ React15.createElement(DropdownMenu3.CheckboxItem, {
|
|
999
|
+
key: id,
|
|
1000
|
+
"aria-labelledby": `${id}__label`,
|
|
1001
|
+
"aria-describedby": `${id}__description`,
|
|
1002
|
+
checked: activeActionKey2 === id,
|
|
1003
|
+
onCheckedChange: (checked) => checked && setActiveAction(id),
|
|
1004
|
+
classNames: "gap-2"
|
|
1005
|
+
}, action.icon && /* @__PURE__ */ React15.createElement(action.icon, {
|
|
1006
|
+
className: getSize8(5)
|
|
1007
|
+
}), /* @__PURE__ */ React15.createElement("div", {
|
|
1008
|
+
role: "none",
|
|
1009
|
+
className: "flex-1 min-is-0 space-b-1"
|
|
1010
|
+
}, /* @__PURE__ */ React15.createElement("p", {
|
|
1011
|
+
id: `${id}__label`
|
|
1012
|
+
}, action.label), action.description && /* @__PURE__ */ React15.createElement("p", {
|
|
1013
|
+
id: `${id}__description`,
|
|
1014
|
+
className: descriptionText5
|
|
1015
|
+
}, action.description)), /* @__PURE__ */ React15.createElement(DropdownMenu3.ItemIndicator, {
|
|
1016
|
+
asChild: true
|
|
1017
|
+
}, /* @__PURE__ */ React15.createElement(Check3, {
|
|
1018
|
+
weight: "bold",
|
|
1019
|
+
className: getSize8(4)
|
|
1020
|
+
})));
|
|
1021
|
+
})), /* @__PURE__ */ React15.createElement(DropdownMenu3.Arrow, null))));
|
|
1022
|
+
});
|
|
1023
|
+
var Action = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
|
|
1024
|
+
const { children, classNames, variant, isFull = true, ...rest } = props;
|
|
1025
|
+
return /* @__PURE__ */ React15.createElement(Button8, {
|
|
1026
|
+
...rest,
|
|
1027
|
+
classNames: [
|
|
1028
|
+
isFull && "is-full",
|
|
1029
|
+
"bs-11 flex gap-2 mbs-2",
|
|
1030
|
+
classNames
|
|
1031
|
+
],
|
|
1032
|
+
ref: forwardedRef,
|
|
1033
|
+
variant
|
|
1034
|
+
}, children);
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
// packages/sdk/shell/src/components/Panel/Actions.tsx
|
|
1038
|
+
import React16, { forwardRef as forwardRef4 } from "react";
|
|
1039
|
+
import { mx as mx12 } from "@dxos/react-ui-theme";
|
|
1040
|
+
var Actions = /* @__PURE__ */ forwardRef4(({ classNames, children, ...props }, forwardedRef) => {
|
|
1041
|
+
return /* @__PURE__ */ React16.createElement("div", {
|
|
1042
|
+
...props,
|
|
1043
|
+
className: mx12("flex flex-col gap-2 mbs-2", Array.isArray(children) && children.length > 1 ? "justify-between" : "justify-center", classNames),
|
|
1044
|
+
ref: forwardedRef
|
|
1045
|
+
}, children);
|
|
1046
|
+
});
|
|
1047
|
+
|
|
1048
|
+
// packages/sdk/shell/src/components/Panel/CloseButton.tsx
|
|
1049
|
+
import { X as X2 } from "@phosphor-icons/react";
|
|
1050
|
+
import React17 from "react";
|
|
1051
|
+
import { Button as Button9, useTranslation as useTranslation10 } from "@dxos/react-ui";
|
|
1052
|
+
import { getSize as getSize9, mx as mx13 } from "@dxos/react-ui-theme";
|
|
1053
|
+
var CloseButton = ({ onDone, ...props }) => {
|
|
1054
|
+
const { t } = useTranslation10("os");
|
|
1055
|
+
return /* @__PURE__ */ React17.createElement(Button9, {
|
|
1056
|
+
variant: "ghost",
|
|
1057
|
+
classNames: mx13("plb-0 pli-2 absolute block-start-0 inline-end-0 z-[1]"),
|
|
1058
|
+
onClick: () => onDone?.(),
|
|
1059
|
+
...props
|
|
1060
|
+
}, /* @__PURE__ */ React17.createElement(X2, {
|
|
1061
|
+
weight: "bold",
|
|
1062
|
+
className: getSize9(4)
|
|
1063
|
+
}), /* @__PURE__ */ React17.createElement("span", {
|
|
1064
|
+
className: "sr-only"
|
|
1065
|
+
}, t("exit label")));
|
|
1066
|
+
};
|
|
1067
|
+
|
|
1068
|
+
// packages/sdk/shell/src/components/Panel/Emoji.tsx
|
|
1069
|
+
import React18 from "react";
|
|
1070
|
+
import { mx as mx14, getSize as getSize10 } from "@dxos/react-ui-theme";
|
|
1071
|
+
var Emoji = ({ text, className }) => {
|
|
1072
|
+
const size = 14;
|
|
1073
|
+
return /* @__PURE__ */ React18.createElement("div", {
|
|
1074
|
+
role: "none",
|
|
1075
|
+
className: mx14(getSize10(size), "rounded relative pointer-events-none", className)
|
|
1076
|
+
}, /* @__PURE__ */ React18.createElement("svg", {
|
|
1077
|
+
viewBox: `0 0 ${size * 4} ${size * 4}`,
|
|
1078
|
+
width: size * 4,
|
|
1079
|
+
height: size * 4
|
|
1080
|
+
}, /* @__PURE__ */ React18.createElement("text", {
|
|
1081
|
+
x: "50%",
|
|
1082
|
+
y: "50%",
|
|
1083
|
+
textAnchor: "middle",
|
|
1084
|
+
dominantBaseline: "middle",
|
|
1085
|
+
baselineShift: "-0.25rem",
|
|
1086
|
+
fontSize: "2.25rem"
|
|
1087
|
+
}, text)));
|
|
1088
|
+
};
|
|
1089
|
+
var Centered = (props) => {
|
|
1090
|
+
const { children } = props;
|
|
1091
|
+
return /* @__PURE__ */ React18.createElement("div", {
|
|
1092
|
+
role: "none",
|
|
1093
|
+
className: "absolute inset-0 flex items-center justify-center"
|
|
1094
|
+
}, children);
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1097
|
+
// packages/sdk/shell/src/components/Panel/Heading.tsx
|
|
1098
|
+
import React19, { forwardRef as forwardRef5 } from "react";
|
|
1099
|
+
import { descriptionText as descriptionText6, mx as mx15 } from "@dxos/react-ui-theme";
|
|
1100
|
+
var Heading = /* @__PURE__ */ forwardRef5(({ titleId, title, titleSrOnly, children, corner }, forwardedRef) => {
|
|
1101
|
+
return /* @__PURE__ */ React19.createElement("div", {
|
|
1102
|
+
role: "none",
|
|
1103
|
+
className: "pbe-2 relative",
|
|
1104
|
+
ref: forwardedRef
|
|
1105
|
+
}, corner, /* @__PURE__ */ React19.createElement("h1", {
|
|
1106
|
+
...!titleSrOnly && {
|
|
1107
|
+
id: titleId
|
|
1108
|
+
},
|
|
1109
|
+
className: mx15(descriptionText6, "text-center mlb-2", titleSrOnly && "invisible")
|
|
1110
|
+
}, title), titleSrOnly && /* @__PURE__ */ React19.createElement("span", {
|
|
1111
|
+
id: titleId
|
|
1112
|
+
}, title), children);
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
// packages/sdk/shell/src/components/Panel/Label.tsx
|
|
1116
|
+
import React20 from "react";
|
|
1117
|
+
import { descriptionText as descriptionText7, mx as mx16 } from "@dxos/react-ui-theme";
|
|
1118
|
+
var Label = (props) => {
|
|
1119
|
+
const { children } = props;
|
|
1120
|
+
return /* @__PURE__ */ React20.createElement("span", {
|
|
1121
|
+
className: mx16(descriptionText7, "text-center mli-6 whitespace-normal")
|
|
1122
|
+
}, children);
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
// packages/sdk/shell/src/components/Panel/Input.tsx
|
|
1126
|
+
import React21 from "react";
|
|
1127
|
+
import { Input as UiInput } from "@dxos/react-ui";
|
|
1128
|
+
var Input = ({ validationMessage, label, ...props }) => {
|
|
1129
|
+
return /* @__PURE__ */ React21.createElement(UiInput.Root, null, /* @__PURE__ */ React21.createElement(UiInput.Label, null, label), /* @__PURE__ */ React21.createElement(UiInput.TextInput, {
|
|
1130
|
+
...props,
|
|
1131
|
+
classNames: "plb-3 mbs-2 text-center"
|
|
1132
|
+
}), /* @__PURE__ */ React21.createElement(UiInput.DescriptionAndValidation, null, validationMessage && /* @__PURE__ */ React21.createElement(UiInput.Validation, null, validationMessage)));
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
// packages/sdk/shell/src/components/Panel/StepHeading.tsx
|
|
1136
|
+
import React22, { forwardRef as forwardRef6 } from "react";
|
|
1137
|
+
import { mx as mx17 } from "@dxos/react-ui-theme";
|
|
1138
|
+
var StepHeading = /* @__PURE__ */ forwardRef6(({ children, className, ...props }, forwardedRef) => {
|
|
1139
|
+
return /* @__PURE__ */ React22.createElement("h2", {
|
|
1140
|
+
...props,
|
|
1141
|
+
className: mx17("font-normal text-sm mbe-4 mli-1 text-center", className),
|
|
1142
|
+
ref: forwardedRef
|
|
1143
|
+
}, children);
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
// packages/sdk/shell/src/components/Viewport/Viewport.tsx
|
|
1147
|
+
import { useFocusFinders } from "@fluentui/react-tabster";
|
|
1148
|
+
import { createContextScope } from "@radix-ui/react-context";
|
|
1149
|
+
import { useControllableState as useControllableState4 } from "@radix-ui/react-use-controllable-state";
|
|
1150
|
+
import React23, { forwardRef as forwardRef7, useEffect } from "react";
|
|
1151
|
+
import { useForwardedRef } from "@dxos/react-ui";
|
|
1152
|
+
import { mx as mx18 } from "@dxos/react-ui-theme";
|
|
1153
|
+
var VIEWPORT_NAME = "Viewport";
|
|
1154
|
+
var VIEWS_NAME = "ViewportViews";
|
|
1155
|
+
var VIEW_NAME = "ViewportView";
|
|
1156
|
+
var [createViewportContext, createViewportScope] = createContextScope(VIEWPORT_NAME, []);
|
|
1157
|
+
var [ViewportProvider, useViewportContext] = createViewportContext(VIEWPORT_NAME);
|
|
1158
|
+
var ViewportRoot = ({ __viewportScope, classNames, children, defaultActiveView, activeView: propsActiveView, focusManaged = false, onActiveViewChange, ...props }) => {
|
|
1159
|
+
const [activeView = "never", setActiveView] = useControllableState4({
|
|
1160
|
+
prop: propsActiveView,
|
|
1161
|
+
defaultProp: defaultActiveView,
|
|
1162
|
+
onChange: onActiveViewChange
|
|
1163
|
+
});
|
|
1164
|
+
return /* @__PURE__ */ React23.createElement(ViewportProvider, {
|
|
1165
|
+
focusManaged,
|
|
1166
|
+
activeView,
|
|
1167
|
+
setActiveView,
|
|
1168
|
+
scope: __viewportScope
|
|
1169
|
+
}, /* @__PURE__ */ React23.createElement("div", {
|
|
1170
|
+
role: "region",
|
|
1171
|
+
"aria-live": "polite",
|
|
1172
|
+
...props,
|
|
1173
|
+
className: mx18("is-full overflow-hidden", classNames)
|
|
1174
|
+
}, children));
|
|
1175
|
+
};
|
|
1176
|
+
ViewportRoot.displayName = VIEWPORT_NAME;
|
|
1177
|
+
var ViewportViews = ({ classNames, children, ...props }) => {
|
|
1178
|
+
const size = {
|
|
1179
|
+
inlineSize: `${Math.ceil(children.length) * 100}%`
|
|
1180
|
+
};
|
|
1181
|
+
return /* @__PURE__ */ React23.createElement("div", {
|
|
1182
|
+
role: "none",
|
|
1183
|
+
style: size,
|
|
1184
|
+
...props,
|
|
1185
|
+
className: mx18("flex", classNames)
|
|
1186
|
+
}, children);
|
|
1187
|
+
};
|
|
1188
|
+
ViewportViews.displayName = VIEWS_NAME;
|
|
1189
|
+
var ViewportView = /* @__PURE__ */ forwardRef7(({ __viewportScope, classNames, children, id, ...props }, forwardedRef) => {
|
|
1190
|
+
const { activeView, focusManaged } = useViewportContext(VIEW_NAME, __viewportScope);
|
|
1191
|
+
const isActive = id === activeView;
|
|
1192
|
+
const ref = useForwardedRef(forwardedRef);
|
|
1193
|
+
const { findFirstFocusable } = useFocusFinders();
|
|
1194
|
+
useEffect(() => {
|
|
1195
|
+
if (!focusManaged && isActive && document.body.hasAttribute("data-is-keyboard") && ref.current) {
|
|
1196
|
+
findFirstFocusable(ref.current)?.focus();
|
|
1197
|
+
}
|
|
1198
|
+
}, [
|
|
1199
|
+
focusManaged,
|
|
1200
|
+
ref.current,
|
|
1201
|
+
isActive
|
|
1202
|
+
]);
|
|
1203
|
+
return /* @__PURE__ */ React23.createElement("section", {
|
|
1204
|
+
...props,
|
|
1205
|
+
...!isActive && {
|
|
1206
|
+
"aria-hidden": true
|
|
1207
|
+
},
|
|
1208
|
+
className: mx18("min-is-0 flex-1 flex flex-col", isActive ? "order-2" : "order-4 invisible", classNames),
|
|
1209
|
+
ref
|
|
1210
|
+
}, children);
|
|
1211
|
+
});
|
|
1212
|
+
ViewportView.displayName = VIEW_NAME;
|
|
1213
|
+
var Viewport = {
|
|
1214
|
+
Root: ViewportRoot,
|
|
1215
|
+
Views: ViewportViews,
|
|
1216
|
+
View: ViewportView
|
|
1217
|
+
};
|
|
1218
|
+
|
|
1219
|
+
// packages/sdk/shell/src/components/SpaceListItem.tsx
|
|
1220
|
+
import React24, { forwardRef as forwardRef8 } from "react";
|
|
1221
|
+
import { Avatar as Avatar5, useId as useId4 } from "@dxos/react-ui";
|
|
1222
|
+
import { mx as mx19 } from "@dxos/react-ui-theme";
|
|
1223
|
+
import { humanize, keyToEmoji } from "@dxos/util";
|
|
1224
|
+
var SpaceListItem = /* @__PURE__ */ forwardRef8(({ space, onClick }, ref) => {
|
|
1225
|
+
const fallbackValue = keyToEmoji(space.key);
|
|
1226
|
+
const labelId = useId4("identityListItem__label");
|
|
1227
|
+
const displayName = space.properties.name ?? humanize(space.key.toHex());
|
|
1228
|
+
return /* @__PURE__ */ React24.createElement("li", {
|
|
1229
|
+
className: mx19("flex gap-2 items-center mbe-2", onClick && "cursor-pointer"),
|
|
1230
|
+
onClick: () => onClick?.(),
|
|
1231
|
+
ref,
|
|
1232
|
+
"data-testid": "space-list-item"
|
|
1233
|
+
}, /* @__PURE__ */ React24.createElement(Avatar5.Root, {
|
|
1234
|
+
labelId
|
|
1235
|
+
}, /* @__PURE__ */ React24.createElement(Avatar5.Frame, null, /* @__PURE__ */ React24.createElement(Avatar5.Fallback, {
|
|
1236
|
+
text: fallbackValue
|
|
1237
|
+
})), /* @__PURE__ */ React24.createElement(Avatar5.Label, {
|
|
1238
|
+
classNames: "text-sm truncate"
|
|
1239
|
+
}, displayName)));
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// packages/sdk/shell/src/composites/IdentityDialog/IdentityDialog.tsx
|
|
1243
|
+
import React42 from "react";
|
|
1244
|
+
import { Dialog, useId as useId10 } from "@dxos/react-ui";
|
|
1245
|
+
|
|
1246
|
+
// packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx
|
|
1247
|
+
import { FirstAidKit as FirstAidKit2, Key, Plugs, PlugsConnected } from "@phosphor-icons/react";
|
|
1248
|
+
import React29, { useEffect as useEffect4, useMemo as useMemo3, useState as useState9 } from "react";
|
|
1249
|
+
import { generateName as generateName3 } from "@dxos/display-name";
|
|
1250
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1251
|
+
import { log as log6 } from "@dxos/log";
|
|
1252
|
+
import { useClient as useClient6 } from "@dxos/react-client";
|
|
1253
|
+
import { useIdentity, useDevices, useHaloInvitations as useHaloInvitations2 } from "@dxos/react-client/halo";
|
|
1254
|
+
import { useInvitationStatus as useInvitationStatus2 } from "@dxos/react-client/invitations";
|
|
1255
|
+
import { useNetworkStatus, ConnectionState as ConnectionState2 } from "@dxos/react-client/mesh";
|
|
1256
|
+
import { Avatar as Avatar6, Input as Input2, Toolbar as Toolbar3, Tooltip as Tooltip7, useId as useId6, useTranslation as useTranslation14 } from "@dxos/react-ui";
|
|
1257
|
+
import { getSize as getSize13 } from "@dxos/react-ui-theme";
|
|
1258
|
+
import { hexToEmoji as hexToEmoji4, hexToHue as hexToHue2, keyToFallback as keyToFallback3 } from "@dxos/util";
|
|
1259
|
+
|
|
1260
|
+
// packages/sdk/shell/src/panels/IdentityPanel/identityMachine.ts
|
|
1261
|
+
import { useMachine } from "@xstate/react";
|
|
1262
|
+
import { assign, createMachine } from "xstate";
|
|
1263
|
+
import { log } from "@dxos/log";
|
|
1264
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/identityMachine.ts";
|
|
1265
|
+
var identityMachine = createMachine({
|
|
1266
|
+
id: "identity",
|
|
1267
|
+
predictableActionArguments: true,
|
|
1268
|
+
context: {
|
|
1269
|
+
identity: null,
|
|
1270
|
+
identitySubscribable: null
|
|
1271
|
+
},
|
|
1272
|
+
initial: "choosingAction",
|
|
1273
|
+
invoke: {
|
|
1274
|
+
src: (context) => context.identitySubscribable
|
|
1275
|
+
},
|
|
1276
|
+
states: {
|
|
1277
|
+
unknown: {
|
|
1278
|
+
always: [
|
|
1279
|
+
{
|
|
1280
|
+
cond: "initiallyManagingDeviceInvitation",
|
|
1281
|
+
target: "managingDeviceInvitation",
|
|
1282
|
+
actions: "log"
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
target: "choosingAction",
|
|
1286
|
+
actions: "log"
|
|
1287
|
+
}
|
|
1288
|
+
]
|
|
1289
|
+
},
|
|
1290
|
+
choosingAction: {},
|
|
1291
|
+
managingDeviceInvitation: {},
|
|
1292
|
+
confirmingResetStorage: {},
|
|
1293
|
+
confirmingRecover: {},
|
|
1294
|
+
confirmingJoinNewIdentity: {}
|
|
1295
|
+
},
|
|
1296
|
+
on: {
|
|
1297
|
+
unchooseAction: {
|
|
1298
|
+
target: ".choosingAction",
|
|
1299
|
+
actions: [
|
|
1300
|
+
"unsetInvitation",
|
|
1301
|
+
"log"
|
|
1302
|
+
]
|
|
1303
|
+
},
|
|
1304
|
+
deselectInvitation: {
|
|
1305
|
+
target: ".choosingAction",
|
|
1306
|
+
actions: [
|
|
1307
|
+
"unsetInvitation",
|
|
1308
|
+
"log"
|
|
1309
|
+
]
|
|
1310
|
+
},
|
|
1311
|
+
selectInvitation: {
|
|
1312
|
+
target: ".managingDeviceInvitation",
|
|
1313
|
+
actions: [
|
|
1314
|
+
"setInvitation",
|
|
1315
|
+
"log"
|
|
1316
|
+
]
|
|
1317
|
+
},
|
|
1318
|
+
chooseJoinNewIdentity: {
|
|
1319
|
+
target: ".confirmingJoinNewIdentity",
|
|
1320
|
+
actions: "log"
|
|
1321
|
+
},
|
|
1322
|
+
chooseRecoverIdentity: {
|
|
1323
|
+
target: ".confirmingRecover",
|
|
1324
|
+
actions: "log"
|
|
1325
|
+
},
|
|
1326
|
+
chooseResetStorage: {
|
|
1327
|
+
target: ".confirmingResetStorage",
|
|
1328
|
+
actions: "log"
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}, {
|
|
1332
|
+
guards: {
|
|
1333
|
+
initiallyManagingDeviceInvitation: ({ initialDisposition }, _event) => initialDisposition === "manage-device-invitation"
|
|
1334
|
+
},
|
|
1335
|
+
actions: {
|
|
1336
|
+
setIdentity: assign({
|
|
1337
|
+
identity: (context, event) => event?.identity ?? null
|
|
1338
|
+
}),
|
|
1339
|
+
setInvitation: assign({
|
|
1340
|
+
invitation: (context, event) => event?.invitation ?? null
|
|
1341
|
+
}),
|
|
1342
|
+
unsetInvitation: assign({
|
|
1343
|
+
invitation: () => void 0
|
|
1344
|
+
}),
|
|
1345
|
+
log: (context, event) => {
|
|
1346
|
+
log("[transition]", {
|
|
1347
|
+
event,
|
|
1348
|
+
context
|
|
1349
|
+
}, {
|
|
1350
|
+
F: __dxlog_file,
|
|
1351
|
+
L: 98,
|
|
1352
|
+
S: void 0,
|
|
1353
|
+
C: (f, a) => f(...a)
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
var useIdentityMachine = (client, options) => {
|
|
1359
|
+
return useMachine(identityMachine, {
|
|
1360
|
+
...options,
|
|
1361
|
+
context: {
|
|
1362
|
+
...options?.context,
|
|
1363
|
+
identity: client.halo.identity.get(),
|
|
1364
|
+
identitySubscribable: client.halo.identity.map((identity) => ({
|
|
1365
|
+
type: "setIdentity",
|
|
1366
|
+
identity
|
|
1367
|
+
}))
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
// packages/sdk/shell/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx
|
|
1373
|
+
import React25 from "react";
|
|
1374
|
+
import { log as log2 } from "@dxos/log";
|
|
1375
|
+
import { useClient as useClient2 } from "@dxos/react-client";
|
|
1376
|
+
import { useHaloInvitations, DeviceType as DeviceType2 } from "@dxos/react-client/halo";
|
|
1377
|
+
import { Invitation as Invitation2, InvitationEncoder } from "@dxos/react-client/invitations";
|
|
1378
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx";
|
|
1379
|
+
var IdentityActionChooser = (props) => {
|
|
1380
|
+
const { send } = props;
|
|
1381
|
+
const client = useClient2();
|
|
1382
|
+
const invitations = useHaloInvitations();
|
|
1383
|
+
const createInvitation = () => {
|
|
1384
|
+
invitations.forEach((invitation2) => invitation2.cancel());
|
|
1385
|
+
const invitation = client.halo.share();
|
|
1386
|
+
if (client.config.values.runtime?.app?.env?.DX_ENVIRONMENT !== "production") {
|
|
1387
|
+
const subscription = invitation.subscribe((invitation2) => {
|
|
1388
|
+
const invitationCode = InvitationEncoder.encode(invitation2);
|
|
1389
|
+
if (invitation2.state === Invitation2.State.CONNECTING) {
|
|
1390
|
+
log2.info(JSON.stringify({
|
|
1391
|
+
invitationCode,
|
|
1392
|
+
authCode: invitation2.authCode
|
|
1393
|
+
}), void 0, {
|
|
1394
|
+
F: __dxlog_file2,
|
|
1395
|
+
L: 29,
|
|
1396
|
+
S: void 0,
|
|
1397
|
+
C: (f, a) => f(...a)
|
|
1398
|
+
});
|
|
1399
|
+
subscription.unsubscribe();
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
send?.({
|
|
1404
|
+
type: "selectInvitation",
|
|
1405
|
+
invitation
|
|
1406
|
+
});
|
|
1407
|
+
};
|
|
1408
|
+
const isProduction = client.config.values.runtime?.app?.env?.DX_ENVIRONMENT === "production";
|
|
1409
|
+
return /* @__PURE__ */ React25.createElement(IdentityActionChooserImpl, {
|
|
1410
|
+
...props,
|
|
1411
|
+
onClickAdd: createInvitation,
|
|
1412
|
+
onClickJoinExisting: () => send?.({
|
|
1413
|
+
type: "chooseJoinNewIdentity"
|
|
1414
|
+
}),
|
|
1415
|
+
onClickRecover: isProduction ? void 0 : () => send?.({
|
|
1416
|
+
type: "chooseRecoverIdentity"
|
|
1417
|
+
}),
|
|
1418
|
+
onClickReset: () => send?.({
|
|
1419
|
+
type: "chooseResetStorage"
|
|
1420
|
+
})
|
|
1421
|
+
});
|
|
1422
|
+
};
|
|
1423
|
+
var IdentityActionChooserImpl = ({ devices, connectionState, agentHostingEnabled, onClickAdd, onClickJoinExisting, onClickRecover, onClickReset, ...agentProps }) => {
|
|
1424
|
+
const managedDeviceAvailable = devices.find((device) => device.profile?.type === DeviceType2.AGENT_MANAGED);
|
|
1425
|
+
return /* @__PURE__ */ React25.createElement("div", {
|
|
1426
|
+
role: "none",
|
|
1427
|
+
className: "bs-40 grow overflow-y-auto overflow-x-hidden"
|
|
1428
|
+
}, /* @__PURE__ */ React25.createElement(DeviceList, {
|
|
1429
|
+
devices,
|
|
1430
|
+
connectionState,
|
|
1431
|
+
onClickAdd,
|
|
1432
|
+
onClickJoinExisting,
|
|
1433
|
+
onClickRecover: agentProps.agentStatus === "created" ? onClickRecover : void 0,
|
|
1434
|
+
onClickReset,
|
|
1435
|
+
onAgentDestroy: agentProps.onAgentDestroy
|
|
1436
|
+
}), !managedDeviceAvailable && agentHostingEnabled && /* @__PURE__ */ React25.createElement(AgentConfig, agentProps));
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
// packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx
|
|
1440
|
+
import React26, { useState as useState5 } from "react";
|
|
1441
|
+
import { log as log3 } from "@dxos/log";
|
|
1442
|
+
import { useTranslation as useTranslation11 } from "@dxos/react-ui";
|
|
1443
|
+
import { hexToEmoji as hexToEmoji2, hexToHue } from "@dxos/util";
|
|
1444
|
+
|
|
1445
|
+
// packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts
|
|
1446
|
+
import { useClient as useClient5 } from "@dxos/react-client";
|
|
1447
|
+
|
|
1448
|
+
// packages/sdk/shell/src/panels/IdentityPanel/useEdgeAgentsHandlers.ts
|
|
1449
|
+
import { useEffect as useEffect2, useState as useState6 } from "react";
|
|
1450
|
+
import { invariant } from "@dxos/invariant";
|
|
1451
|
+
import { QueryAgentStatusResponse } from "@dxos/protocols/proto/dxos/client/services";
|
|
1452
|
+
import { EdgeReplicationSetting } from "@dxos/protocols/proto/dxos/echo/metadata";
|
|
1453
|
+
import { useClient as useClient3 } from "@dxos/react-client";
|
|
1454
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/useEdgeAgentsHandlers.ts";
|
|
1455
|
+
var useEdgeAgentHandlers = ({ identity }) => {
|
|
1456
|
+
const [validationMessage, setValidationMessage] = useState6("");
|
|
1457
|
+
const [lastReceivedStatus, setLastReceivedStatus] = useState6(QueryAgentStatusResponse.AgentStatus.UNKNOWN);
|
|
1458
|
+
const [agentStatus, setAgentStatus] = useState6("getting");
|
|
1459
|
+
const client = useClient3();
|
|
1460
|
+
const agentHostingEnabled = Boolean(client.config.values.runtime?.client?.edgeFeatures?.agents);
|
|
1461
|
+
const handleStatus = (status) => {
|
|
1462
|
+
switch (status) {
|
|
1463
|
+
case QueryAgentStatusResponse.AgentStatus.ACTIVE:
|
|
1464
|
+
case QueryAgentStatusResponse.AgentStatus.INACTIVE:
|
|
1465
|
+
setAgentStatus("created");
|
|
1466
|
+
break;
|
|
1467
|
+
case QueryAgentStatusResponse.AgentStatus.NOT_FOUND:
|
|
1468
|
+
setAgentStatus("creatable");
|
|
1469
|
+
break;
|
|
1470
|
+
case QueryAgentStatusResponse.AgentStatus.UNKNOWN:
|
|
1471
|
+
setAgentStatus("getting");
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
useEffect2(() => {
|
|
1476
|
+
const stream = client.services.services.EdgeAgentService?.queryAgentStatus();
|
|
1477
|
+
stream?.subscribe(({ status }) => {
|
|
1478
|
+
setLastReceivedStatus(status);
|
|
1479
|
+
handleStatus(status);
|
|
1480
|
+
});
|
|
1481
|
+
return () => {
|
|
1482
|
+
void stream?.close().catch(() => {
|
|
1483
|
+
});
|
|
1484
|
+
};
|
|
1485
|
+
}, []);
|
|
1486
|
+
const onAgentCreate = async () => {
|
|
1487
|
+
invariant(identity, "Identity not found", {
|
|
1488
|
+
F: __dxlog_file3,
|
|
1489
|
+
L: 58,
|
|
1490
|
+
S: void 0,
|
|
1491
|
+
A: [
|
|
1492
|
+
"identity",
|
|
1493
|
+
"'Identity not found'"
|
|
1494
|
+
]
|
|
1495
|
+
});
|
|
1496
|
+
const service = client.services.services.EdgeAgentService;
|
|
1497
|
+
if (!service) {
|
|
1498
|
+
setAgentStatus("error");
|
|
1499
|
+
setValidationMessage("Agent service not initialized.");
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (!agentHostingEnabled) {
|
|
1503
|
+
setAgentStatus("error");
|
|
1504
|
+
setValidationMessage("Edge agents are disabled in config.");
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
setAgentStatus("creating");
|
|
1508
|
+
setValidationMessage("");
|
|
1509
|
+
try {
|
|
1510
|
+
await service.createAgent();
|
|
1511
|
+
await Promise.all(client.spaces.get().map((space) => space?.internal.setEdgeReplicationPreference(EdgeReplicationSetting.ENABLED)));
|
|
1512
|
+
setAgentStatus("created");
|
|
1513
|
+
} catch (err) {
|
|
1514
|
+
setAgentStatus("error");
|
|
1515
|
+
setValidationMessage(`Error creating an agent: ${err.message}`);
|
|
1516
|
+
}
|
|
1517
|
+
};
|
|
1518
|
+
const onAgentDestroy = async () => {
|
|
1519
|
+
setValidationMessage("Agents are non-destructible.");
|
|
1520
|
+
};
|
|
1521
|
+
const onAgentRefresh = async () => {
|
|
1522
|
+
setValidationMessage("");
|
|
1523
|
+
handleStatus(lastReceivedStatus);
|
|
1524
|
+
};
|
|
1525
|
+
return {
|
|
1526
|
+
onAgentCreate,
|
|
1527
|
+
onAgentDestroy,
|
|
1528
|
+
onAgentRefresh,
|
|
1529
|
+
validationMessage,
|
|
1530
|
+
agentStatus,
|
|
1531
|
+
agentHostingEnabled
|
|
1532
|
+
};
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
// packages/sdk/shell/src/panels/IdentityPanel/useKubeAgentHandlers.ts
|
|
1536
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useState as useState7 } from "react";
|
|
1537
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1538
|
+
import { log as log4 } from "@dxos/log";
|
|
1539
|
+
import { useClient as useClient4, useAgentHostingClient } from "@dxos/react-client";
|
|
1540
|
+
import { Invitation as Invitation3, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
|
|
1541
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/useKubeAgentHandlers.ts";
|
|
1542
|
+
var useKubeAgentHandlers = ({ invitations, identity }) => {
|
|
1543
|
+
const [validationMessage, setValidationMessage] = useState7("");
|
|
1544
|
+
const [agentStatus, setAgentStatus] = useState7("getting");
|
|
1545
|
+
const agentHostingProviderClient = useAgentHostingClient();
|
|
1546
|
+
const client = useClient4();
|
|
1547
|
+
const updateAgentStatus = async () => {
|
|
1548
|
+
if (agentHostingProviderClient) {
|
|
1549
|
+
setAgentStatus("getting");
|
|
1550
|
+
try {
|
|
1551
|
+
const agentId = await agentHostingProviderClient?.getAgent(identity?.identityKey.truncate() ?? "never");
|
|
1552
|
+
if (agentId) {
|
|
1553
|
+
setAgentStatus("created");
|
|
1554
|
+
} else {
|
|
1555
|
+
setAgentStatus("creatable");
|
|
1556
|
+
}
|
|
1557
|
+
} catch (err) {
|
|
1558
|
+
setAgentStatus("error");
|
|
1559
|
+
setValidationMessage(`Couldn\u2019t check agent status: ${err.message}`);
|
|
1560
|
+
}
|
|
1561
|
+
} else {
|
|
1562
|
+
setAgentStatus("error");
|
|
1563
|
+
setValidationMessage("No agent provider configured.");
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
const createAgent = async (invitationCode) => {
|
|
1567
|
+
invariant2(identity, "Identity not found", {
|
|
1568
|
+
F: __dxlog_file4,
|
|
1569
|
+
L: 50,
|
|
1570
|
+
S: void 0,
|
|
1571
|
+
A: [
|
|
1572
|
+
"identity",
|
|
1573
|
+
"'Identity not found'"
|
|
1574
|
+
]
|
|
1575
|
+
});
|
|
1576
|
+
if (agentHostingProviderClient) {
|
|
1577
|
+
setAgentStatus("creating");
|
|
1578
|
+
setValidationMessage("");
|
|
1579
|
+
try {
|
|
1580
|
+
const agentId = await agentHostingProviderClient?.createAgent(invitationCode, identity.identityKey.truncate());
|
|
1581
|
+
if (agentId) {
|
|
1582
|
+
setAgentStatus("created");
|
|
1583
|
+
} else {
|
|
1584
|
+
setAgentStatus("creatable");
|
|
1585
|
+
setValidationMessage("Error creating agent.");
|
|
1586
|
+
}
|
|
1587
|
+
} catch (err) {
|
|
1588
|
+
setValidationMessage(`Error creating agent: ${err.message}`);
|
|
1589
|
+
return updateAgentStatus();
|
|
1590
|
+
}
|
|
1591
|
+
} else {
|
|
1592
|
+
setAgentStatus("error");
|
|
1593
|
+
setValidationMessage("No agent provider configured.");
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
const destroyAgent = async () => {
|
|
1597
|
+
invariant2(identity, "Identity not found", {
|
|
1598
|
+
F: __dxlog_file4,
|
|
1599
|
+
L: 73,
|
|
1600
|
+
S: void 0,
|
|
1601
|
+
A: [
|
|
1602
|
+
"identity",
|
|
1603
|
+
"'Identity not found'"
|
|
1604
|
+
]
|
|
1605
|
+
});
|
|
1606
|
+
if (agentHostingProviderClient) {
|
|
1607
|
+
setAgentStatus("destroying");
|
|
1608
|
+
setValidationMessage("");
|
|
1609
|
+
try {
|
|
1610
|
+
await agentHostingProviderClient?.destroyAgent(identity.identityKey.truncate());
|
|
1611
|
+
setAgentStatus("creatable");
|
|
1612
|
+
} catch (err) {
|
|
1613
|
+
setValidationMessage(`Error destroying agent: ${err.message}`);
|
|
1614
|
+
return updateAgentStatus();
|
|
1615
|
+
}
|
|
1616
|
+
} else {
|
|
1617
|
+
setAgentStatus("error");
|
|
1618
|
+
setValidationMessage("No agent provider configured.");
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
useEffect3(() => {
|
|
1622
|
+
void updateAgentStatus();
|
|
1623
|
+
}, []);
|
|
1624
|
+
const handleAgentCreate = useCallback4(async (invitation) => {
|
|
1625
|
+
const invitationCode = InvitationEncoder2.encode(invitation);
|
|
1626
|
+
if (invitation.state === Invitation3.State.CONNECTING) {
|
|
1627
|
+
log4.info(JSON.stringify({
|
|
1628
|
+
invitationCode,
|
|
1629
|
+
authCode: invitation.authCode
|
|
1630
|
+
}), void 0, {
|
|
1631
|
+
F: __dxlog_file4,
|
|
1632
|
+
L: 97,
|
|
1633
|
+
S: void 0,
|
|
1634
|
+
C: (f, a) => f(...a)
|
|
1635
|
+
});
|
|
1636
|
+
return createAgent(invitationCode);
|
|
1637
|
+
}
|
|
1638
|
+
}, []);
|
|
1639
|
+
const onAgentCreate = async () => {
|
|
1640
|
+
invitations.forEach((invitation2) => invitation2.cancel());
|
|
1641
|
+
const invitation = client.halo.share({
|
|
1642
|
+
type: Invitation3.Type.INTERACTIVE,
|
|
1643
|
+
authMethod: Invitation3.AuthMethod.NONE,
|
|
1644
|
+
multiUse: true
|
|
1645
|
+
});
|
|
1646
|
+
invitation.subscribe(handleAgentCreate);
|
|
1647
|
+
};
|
|
1648
|
+
const onAgentRefresh = async () => {
|
|
1649
|
+
setValidationMessage("");
|
|
1650
|
+
await updateAgentStatus();
|
|
1651
|
+
};
|
|
1652
|
+
return {
|
|
1653
|
+
onAgentCreate,
|
|
1654
|
+
onAgentDestroy: destroyAgent,
|
|
1655
|
+
onAgentRefresh,
|
|
1656
|
+
validationMessage,
|
|
1657
|
+
agentStatus,
|
|
1658
|
+
agentHostingEnabled: !!agentHostingProviderClient
|
|
1659
|
+
};
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
// packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts
|
|
1663
|
+
var useAgentHandlers = (params) => {
|
|
1664
|
+
const client = useClient5();
|
|
1665
|
+
if (client.config.values?.runtime?.client?.edgeFeatures?.agents) {
|
|
1666
|
+
return useEdgeAgentHandlers(params);
|
|
1667
|
+
} else {
|
|
1668
|
+
return useKubeAgentHandlers(params);
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
|
|
1672
|
+
// packages/sdk/shell/src/steps/InvitationManager.tsx
|
|
1673
|
+
import { Check as Check4, X as X3 } from "@phosphor-icons/react";
|
|
1674
|
+
import React27, { useMemo as useMemo2 } from "react";
|
|
1675
|
+
import { QR } from "react-qr-rounded";
|
|
1676
|
+
import { useId as useId5, useTranslation as useTranslation12 } from "@dxos/react-ui";
|
|
1677
|
+
import { descriptionText as descriptionText8, getSize as getSize11, mx as mx20 } from "@dxos/react-ui-theme";
|
|
1678
|
+
import { hexToEmoji as hexToEmoji3 } from "@dxos/util";
|
|
1679
|
+
|
|
1680
|
+
// packages/sdk/shell/src/util/invitationStatusValue.ts
|
|
1681
|
+
import { Invitation as Invitation4 } from "@dxos/react-client/invitations";
|
|
1682
|
+
var invitationStatusValue = /* @__PURE__ */ new Map([
|
|
1683
|
+
[
|
|
1684
|
+
Invitation4.State.ERROR,
|
|
1685
|
+
-3
|
|
1686
|
+
],
|
|
1687
|
+
[
|
|
1688
|
+
Invitation4.State.TIMEOUT,
|
|
1689
|
+
-2
|
|
1690
|
+
],
|
|
1691
|
+
[
|
|
1692
|
+
Invitation4.State.CANCELLED,
|
|
1693
|
+
-1
|
|
1694
|
+
],
|
|
1695
|
+
[
|
|
1696
|
+
Invitation4.State.INIT,
|
|
1697
|
+
0
|
|
1698
|
+
],
|
|
1699
|
+
[
|
|
1700
|
+
Invitation4.State.CONNECTING,
|
|
1701
|
+
1
|
|
1702
|
+
],
|
|
1703
|
+
[
|
|
1704
|
+
Invitation4.State.CONNECTED,
|
|
1705
|
+
2
|
|
1706
|
+
],
|
|
1707
|
+
[
|
|
1708
|
+
Invitation4.State.READY_FOR_AUTHENTICATION,
|
|
1709
|
+
3
|
|
1710
|
+
],
|
|
1711
|
+
[
|
|
1712
|
+
Invitation4.State.AUTHENTICATING,
|
|
1713
|
+
4
|
|
1714
|
+
],
|
|
1715
|
+
[
|
|
1716
|
+
Invitation4.State.SUCCESS,
|
|
1717
|
+
5
|
|
1718
|
+
]
|
|
1719
|
+
]);
|
|
1720
|
+
|
|
1721
|
+
// packages/sdk/shell/src/steps/InvitationManager.tsx
|
|
1722
|
+
var InvitationManagerView = ({ children, ...props }) => {
|
|
1723
|
+
return /* @__PURE__ */ React27.createElement(Viewport.View, {
|
|
1724
|
+
...props,
|
|
1725
|
+
classNames: "grow flex flex-col justify-around items-center"
|
|
1726
|
+
}, children);
|
|
1727
|
+
};
|
|
1728
|
+
var InvitationManager = ({ invitationUrl, active, send, status, multiUse, authCode, id = "0" }) => {
|
|
1729
|
+
const { t } = useTranslation12("os");
|
|
1730
|
+
const qrLabel = useId5("invitation-manager__qr-code");
|
|
1731
|
+
const statusValue = multiUse ? 0 : invitationStatusValue.get(status) ?? 0;
|
|
1732
|
+
const showAuthCode = statusValue === 3;
|
|
1733
|
+
const emoji = hexToEmoji3(id);
|
|
1734
|
+
const activeView = useMemo2(() => {
|
|
1735
|
+
if (multiUse) {
|
|
1736
|
+
return "showing qr";
|
|
1737
|
+
}
|
|
1738
|
+
switch (true) {
|
|
1739
|
+
case statusValue === 5:
|
|
1740
|
+
case statusValue < 0:
|
|
1741
|
+
return "showing final";
|
|
1742
|
+
case statusValue === 3:
|
|
1743
|
+
return "showing auth code";
|
|
1744
|
+
default:
|
|
1745
|
+
return "showing qr";
|
|
1746
|
+
}
|
|
1747
|
+
}, [
|
|
1748
|
+
statusValue
|
|
1749
|
+
]);
|
|
1750
|
+
return /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(Viewport.Root, {
|
|
1751
|
+
activeView,
|
|
1752
|
+
classNames: "grow plb-1"
|
|
1753
|
+
}, /* @__PURE__ */ React27.createElement(Viewport.Views, null, /* @__PURE__ */ React27.createElement(InvitationManagerView, {
|
|
1754
|
+
id: "showing qr",
|
|
1755
|
+
emoji
|
|
1756
|
+
}, /* @__PURE__ */ React27.createElement("p", {
|
|
1757
|
+
className: "text-sm mlb-1 font-normal text-center"
|
|
1758
|
+
}, t(multiUse ? "invite many qr label" : "invite one qr label")), /* @__PURE__ */ React27.createElement("div", {
|
|
1759
|
+
role: "none",
|
|
1760
|
+
className: mx20(descriptionText8, "is-full max-is-[14rem] relative")
|
|
1761
|
+
}, /* @__PURE__ */ React27.createElement(QR, {
|
|
1762
|
+
rounding: 100,
|
|
1763
|
+
backgroundColor: "transparent",
|
|
1764
|
+
color: "currentColor",
|
|
1765
|
+
className: mx20("is-full bs-full p-2", showAuthCode && "invisible"),
|
|
1766
|
+
"aria-labelledby": qrLabel,
|
|
1767
|
+
errorCorrectionLevel: "Q",
|
|
1768
|
+
cutout: true
|
|
1769
|
+
}, invitationUrl ?? "never"), /* @__PURE__ */ React27.createElement(Centered, null, /* @__PURE__ */ React27.createElement(Emoji, {
|
|
1770
|
+
text: emoji
|
|
1771
|
+
}))), /* @__PURE__ */ React27.createElement("span", {
|
|
1772
|
+
id: qrLabel,
|
|
1773
|
+
className: "sr-only"
|
|
1774
|
+
}, t("qr label")), /* @__PURE__ */ React27.createElement(CopyButton, {
|
|
1775
|
+
variant: "ghost",
|
|
1776
|
+
value: invitationUrl ?? "never"
|
|
1777
|
+
})), /* @__PURE__ */ React27.createElement(InvitationManagerView, {
|
|
1778
|
+
id: "showing auth code"
|
|
1779
|
+
}, /* @__PURE__ */ React27.createElement(Label, null, t("auth code message")), /* @__PURE__ */ React27.createElement(AuthCode, {
|
|
1780
|
+
code: authCode,
|
|
1781
|
+
large: true,
|
|
1782
|
+
classNames: "text-black dark:text-white"
|
|
1783
|
+
}), /* @__PURE__ */ React27.createElement(Label, null, t("auth other device emoji message")), emoji && /* @__PURE__ */ React27.createElement(Emoji, {
|
|
1784
|
+
text: emoji
|
|
1785
|
+
})), /* @__PURE__ */ React27.createElement(InvitationManagerView, {
|
|
1786
|
+
id: "showing final"
|
|
1787
|
+
}, statusValue > 0 ? /* @__PURE__ */ React27.createElement(Check4, {
|
|
1788
|
+
className: mx20("m-1.5", getSize11(6))
|
|
1789
|
+
}) : /* @__PURE__ */ React27.createElement(X3, {
|
|
1790
|
+
className: mx20("m-1.5", getSize11(6))
|
|
1791
|
+
})))), /* @__PURE__ */ React27.createElement(Actions, {
|
|
1792
|
+
classNames: "mbs-4"
|
|
1793
|
+
}, /* @__PURE__ */ React27.createElement(Action, {
|
|
1794
|
+
disabled: !active,
|
|
1795
|
+
onClick: () => send?.({
|
|
1796
|
+
type: "deselectInvitation"
|
|
1797
|
+
})
|
|
1798
|
+
}, t("back label"))));
|
|
1799
|
+
};
|
|
1800
|
+
|
|
1801
|
+
// packages/sdk/shell/src/steps/ConfirmReset.tsx
|
|
1802
|
+
import { Warning } from "@phosphor-icons/react";
|
|
1803
|
+
import React28, { useState as useState8 } from "react";
|
|
1804
|
+
import { log as log5 } from "@dxos/log";
|
|
1805
|
+
import { Message, useTranslation as useTranslation13 } from "@dxos/react-ui";
|
|
1806
|
+
import { getSize as getSize12, mx as mx21 } from "@dxos/react-ui-theme";
|
|
1807
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/steps/ConfirmReset.tsx";
|
|
1808
|
+
var ConfirmReset = ({ active, onCancel, onConfirm, mode }) => {
|
|
1809
|
+
const { t } = useTranslation13("os");
|
|
1810
|
+
const [validationMessage, setValidationMessage] = useState8("");
|
|
1811
|
+
const [pending, setPending] = useState8(false);
|
|
1812
|
+
const processReset = async () => {
|
|
1813
|
+
setPending(true);
|
|
1814
|
+
return onConfirm?.().then(() => setPending(false), (error) => {
|
|
1815
|
+
log5.catch(error, void 0, {
|
|
1816
|
+
F: __dxlog_file5,
|
|
1817
|
+
L: 38,
|
|
1818
|
+
S: void 0,
|
|
1819
|
+
C: (f, a) => f(...a)
|
|
1820
|
+
});
|
|
1821
|
+
setValidationMessage(t("failed to reset identity message"));
|
|
1822
|
+
setPending(false);
|
|
1823
|
+
});
|
|
1824
|
+
};
|
|
1825
|
+
return /* @__PURE__ */ React28.createElement(ConfirmResetImpl, {
|
|
1826
|
+
disabled: !active,
|
|
1827
|
+
pending,
|
|
1828
|
+
validationMessage,
|
|
1829
|
+
onConfirm: processReset,
|
|
1830
|
+
onCancel,
|
|
1831
|
+
mode
|
|
1832
|
+
});
|
|
1833
|
+
};
|
|
1834
|
+
var ConfirmResetImpl = ({ disabled, pending, validationMessage, onConfirm, onCancel, mode }) => {
|
|
1835
|
+
const { t } = useTranslation13("os");
|
|
1836
|
+
const confirmationValue = t("confirmation value");
|
|
1837
|
+
const [inputValue, setInputValue] = useState8("");
|
|
1838
|
+
const testIdAffix = mode === "join new identity" ? "join-new-identity" : mode === "recover" ? "recover" : "reset-storage";
|
|
1839
|
+
return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("div", {
|
|
1840
|
+
role: "none",
|
|
1841
|
+
className: "grow flex flex-col gap-2 justify-center"
|
|
1842
|
+
}, /* @__PURE__ */ React28.createElement(Message.Root, {
|
|
1843
|
+
valence: "error"
|
|
1844
|
+
}, /* @__PURE__ */ React28.createElement(Message.Title, null, /* @__PURE__ */ React28.createElement(Warning, {
|
|
1845
|
+
className: mx21(getSize12(6), "inline mie-2")
|
|
1846
|
+
}), t("sign out chooser title")), /* @__PURE__ */ React28.createElement(Message.Body, null, t("sign out chooser message"))), /* @__PURE__ */ React28.createElement(Input, {
|
|
1847
|
+
validationMessage,
|
|
1848
|
+
label: /* @__PURE__ */ React28.createElement(StepHeading, {
|
|
1849
|
+
className: "text-start mlb-2"
|
|
1850
|
+
}, t(mode === "join new identity" ? "join new identity input label" : mode === "recover" ? "recover reset input label" : "reset storage input label", {
|
|
1851
|
+
confirmationValue
|
|
1852
|
+
})),
|
|
1853
|
+
disabled,
|
|
1854
|
+
"data-testid": `${testIdAffix}.reset-identity-input`,
|
|
1855
|
+
placeholder: t("confirmation placeholder", {
|
|
1856
|
+
confirmationValue
|
|
1857
|
+
}),
|
|
1858
|
+
onChange: ({ target: { value } }) => setInputValue(value)
|
|
1859
|
+
})), /* @__PURE__ */ React28.createElement(Actions, null, onCancel && /* @__PURE__ */ React28.createElement(Action, {
|
|
1860
|
+
disabled,
|
|
1861
|
+
onClick: onCancel,
|
|
1862
|
+
"data-testid": `${testIdAffix}.reset-identity-cancel`
|
|
1863
|
+
}, t("cancel label")), onConfirm && /* @__PURE__ */ React28.createElement(Action, {
|
|
1864
|
+
variant: "destructive",
|
|
1865
|
+
disabled: disabled || pending || inputValue !== confirmationValue,
|
|
1866
|
+
onClick: onConfirm,
|
|
1867
|
+
"data-testid": `${testIdAffix}.reset-identity-confirm`
|
|
1868
|
+
}, pending ? t("reset in progress label") : t("reset device label"))));
|
|
1869
|
+
};
|
|
1870
|
+
|
|
1871
|
+
// packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx
|
|
1872
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx";
|
|
1873
|
+
var viewStyles = "pbs-1 pbe-3 pli-3";
|
|
1874
|
+
var getHueValue = (identity) => identity?.profile?.data?.hue || hexToHue2(identity?.identityKey.toHex() ?? "0");
|
|
1875
|
+
var getEmojiValue = (identity) => identity?.profile?.data?.emoji || hexToEmoji4(identity?.identityKey.toHex() ?? "0");
|
|
1876
|
+
var IdentityHeading = ({ titleId, title, identity, hideRecover, onDone, onUpdateProfile, connectionState, onChangeConnectionState }) => {
|
|
1877
|
+
const client = useClient6();
|
|
1878
|
+
const fallbackValue = keyToFallback3(identity.identityKey);
|
|
1879
|
+
const { t } = useTranslation14("os");
|
|
1880
|
+
const [displayName, setDisplayName] = useState9(identity.profile?.displayName ?? "");
|
|
1881
|
+
const [emoji, setEmojiDirectly] = useState9(getEmojiValue(identity));
|
|
1882
|
+
const [hue, setHueDirectly] = useState9(getHueValue(identity));
|
|
1883
|
+
const { textValue, setTextValue } = useClipboardContext();
|
|
1884
|
+
const identityHex = identity.identityKey.toHex();
|
|
1885
|
+
const publicKeyCopied = textValue === identityHex;
|
|
1886
|
+
const setEmoji = (nextEmoji) => {
|
|
1887
|
+
setEmojiDirectly(nextEmoji);
|
|
1888
|
+
void onUpdateProfile?.({
|
|
1889
|
+
...identity.profile,
|
|
1890
|
+
data: {
|
|
1891
|
+
...identity.profile?.data,
|
|
1892
|
+
emoji: nextEmoji
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
};
|
|
1896
|
+
const setHue = (nextHue) => {
|
|
1897
|
+
setHueDirectly(nextHue);
|
|
1898
|
+
void onUpdateProfile?.({
|
|
1899
|
+
...identity.profile,
|
|
1900
|
+
data: {
|
|
1901
|
+
...identity.profile?.data,
|
|
1902
|
+
hue: nextHue
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
};
|
|
1906
|
+
const handleRecoveryCode = async () => {
|
|
1907
|
+
invariant3(client.services.services.IdentityService, "IdentityService not available", {
|
|
1908
|
+
F: __dxlog_file6,
|
|
1909
|
+
L: 77,
|
|
1910
|
+
S: void 0,
|
|
1911
|
+
A: [
|
|
1912
|
+
"client.services.services.IdentityService",
|
|
1913
|
+
"'IdentityService not available'"
|
|
1914
|
+
]
|
|
1915
|
+
});
|
|
1916
|
+
const { seedphrase } = await client.services.services.IdentityService.createRecoveryPhrase();
|
|
1917
|
+
void setTextValue(seedphrase);
|
|
1918
|
+
};
|
|
1919
|
+
const isConnected = connectionState === ConnectionState2.ONLINE;
|
|
1920
|
+
return /* @__PURE__ */ React29.createElement(Heading, {
|
|
1921
|
+
titleId,
|
|
1922
|
+
title,
|
|
1923
|
+
corner: /* @__PURE__ */ React29.createElement(CloseButton, {
|
|
1924
|
+
onDone
|
|
1925
|
+
})
|
|
1926
|
+
}, /* @__PURE__ */ React29.createElement(Avatar6.Root, {
|
|
1927
|
+
size: 16,
|
|
1928
|
+
variant: "circle",
|
|
1929
|
+
status: isConnected ? "active" : "error",
|
|
1930
|
+
hue: hue || fallbackValue.hue
|
|
1931
|
+
}, /* @__PURE__ */ React29.createElement(Toolbar3.Root, {
|
|
1932
|
+
classNames: "flex justify-center"
|
|
1933
|
+
}, /* @__PURE__ */ React29.createElement(Avatar6.Frame, {
|
|
1934
|
+
classNames: "relative z-[2] -mli-4 chromatic-ignore"
|
|
1935
|
+
}, /* @__PURE__ */ React29.createElement(Avatar6.Fallback, {
|
|
1936
|
+
text: emoji || fallbackValue.emoji
|
|
1937
|
+
}))), /* @__PURE__ */ React29.createElement(Avatar6.Label, {
|
|
1938
|
+
classNames: "sr-only",
|
|
1939
|
+
"data-testid": "identityHeading.displayName"
|
|
1940
|
+
}, identity.profile?.displayName ?? generateName3(identity.identityKey.toHex())), /* @__PURE__ */ React29.createElement(Input2.Root, null, /* @__PURE__ */ React29.createElement(Input2.Label, {
|
|
1941
|
+
srOnly: true
|
|
1942
|
+
}, t("display name input label")), /* @__PURE__ */ React29.createElement(Input2.TextInput, {
|
|
1943
|
+
variant: "subdued",
|
|
1944
|
+
"data-testid": "display-name-input",
|
|
1945
|
+
placeholder: t("display name input placeholder"),
|
|
1946
|
+
classNames: "mbs-2 text-center font-light text-xl",
|
|
1947
|
+
value: displayName,
|
|
1948
|
+
onChange: ({ target: { value } }) => setDisplayName(value),
|
|
1949
|
+
onBlur: ({ target: { value } }) => onUpdateProfile?.({
|
|
1950
|
+
...identity.profile,
|
|
1951
|
+
displayName: value
|
|
1952
|
+
})
|
|
1953
|
+
})), /* @__PURE__ */ React29.createElement(Toolbar3.Root, {
|
|
1954
|
+
classNames: "flex justify-center items-center gap-1 pt-3"
|
|
1955
|
+
}, /* @__PURE__ */ React29.createElement(EmojiPickerToolbarButton, {
|
|
1956
|
+
emoji,
|
|
1957
|
+
onChangeEmoji: setEmoji,
|
|
1958
|
+
classNames: "bs-[--rail-action]"
|
|
1959
|
+
}), /* @__PURE__ */ React29.createElement(HuePickerToolbarButton, {
|
|
1960
|
+
hue,
|
|
1961
|
+
onChangeHue: setHue,
|
|
1962
|
+
classNames: "bs-[--rail-action]"
|
|
1963
|
+
}), /* @__PURE__ */ React29.createElement(Tooltip7.Root, null, /* @__PURE__ */ React29.createElement(Tooltip7.Trigger, {
|
|
1964
|
+
asChild: true
|
|
1965
|
+
}, /* @__PURE__ */ React29.createElement(Toolbar3.Button, {
|
|
1966
|
+
classNames: "bs-[--rail-action]",
|
|
1967
|
+
"data-testid": "update-profile-form-copy-key",
|
|
1968
|
+
onClick: () => setTextValue(identityHex)
|
|
1969
|
+
}, /* @__PURE__ */ React29.createElement("span", {
|
|
1970
|
+
className: "sr-only"
|
|
1971
|
+
}, t(publicKeyCopied ? "copy success label" : "copy self public key label")), /* @__PURE__ */ React29.createElement(Key, {
|
|
1972
|
+
className: getSize13(5)
|
|
1973
|
+
}))), /* @__PURE__ */ React29.createElement(Tooltip7.Portal, null, /* @__PURE__ */ React29.createElement(Tooltip7.Content, {
|
|
1974
|
+
side: "bottom",
|
|
1975
|
+
classNames: "z-50"
|
|
1976
|
+
}, t(publicKeyCopied ? "copy success label" : "copy self public key label"), /* @__PURE__ */ React29.createElement(Tooltip7.Arrow, null)))), !hideRecover && /* @__PURE__ */ React29.createElement(Tooltip7.Root, null, /* @__PURE__ */ React29.createElement(Tooltip7.Trigger, {
|
|
1977
|
+
asChild: true
|
|
1978
|
+
}, /* @__PURE__ */ React29.createElement(Toolbar3.Button, {
|
|
1979
|
+
classNames: "bs-[--rail-action]",
|
|
1980
|
+
onClick: handleRecoveryCode
|
|
1981
|
+
}, /* @__PURE__ */ React29.createElement(FirstAidKit2, {
|
|
1982
|
+
className: getSize13(5)
|
|
1983
|
+
}))), /* @__PURE__ */ React29.createElement(Tooltip7.Portal, null, /* @__PURE__ */ React29.createElement(Tooltip7.Content, {
|
|
1984
|
+
side: "bottom",
|
|
1985
|
+
classNames: "z-50"
|
|
1986
|
+
}, t("create recovery code label"), /* @__PURE__ */ React29.createElement(Tooltip7.Arrow, null)))), /* @__PURE__ */ React29.createElement(Tooltip7.Root, null, /* @__PURE__ */ React29.createElement(Tooltip7.Trigger, {
|
|
1987
|
+
asChild: true
|
|
1988
|
+
}, /* @__PURE__ */ React29.createElement(Toolbar3.Button, {
|
|
1989
|
+
classNames: [
|
|
1990
|
+
"bs-[--rail-action]",
|
|
1991
|
+
!isConnected && "text-error-500"
|
|
1992
|
+
],
|
|
1993
|
+
onClick: () => onChangeConnectionState?.(isConnected ? ConnectionState2.OFFLINE : ConnectionState2.ONLINE)
|
|
1994
|
+
}, /* @__PURE__ */ React29.createElement("span", {
|
|
1995
|
+
className: "sr-only"
|
|
1996
|
+
}, t(isConnected ? "disconnect label" : "connect label")), isConnected ? /* @__PURE__ */ React29.createElement(PlugsConnected, {
|
|
1997
|
+
className: getSize13(5)
|
|
1998
|
+
}) : /* @__PURE__ */ React29.createElement(Plugs, {
|
|
1999
|
+
className: getSize13(5)
|
|
2000
|
+
}))), /* @__PURE__ */ React29.createElement(Tooltip7.Portal, null, /* @__PURE__ */ React29.createElement(Tooltip7.Content, {
|
|
2001
|
+
side: "bottom",
|
|
2002
|
+
classNames: "z-50"
|
|
2003
|
+
}, t(isConnected ? "disconnect label" : "connect label"), /* @__PURE__ */ React29.createElement(Tooltip7.Arrow, null)))))));
|
|
2004
|
+
};
|
|
2005
|
+
var IdentityPanelImpl = (props) => {
|
|
2006
|
+
const { identity, titleId, activeView, onUpdateProfile, onResetStorage, onRecover, onJoinNewIdentity, IdentityActionChooser: IdentityActionChooserComponent = IdentityActionChooser, InvitationManager: InvitationManagerComponent = InvitationManager, connectionState, onChangeConnectionState, onDone, ...rest } = props;
|
|
2007
|
+
const { t } = useTranslation14("os");
|
|
2008
|
+
const title = useMemo3(() => {
|
|
2009
|
+
switch (activeView) {
|
|
2010
|
+
case "device invitation manager":
|
|
2011
|
+
return t("choose add device label");
|
|
2012
|
+
default:
|
|
2013
|
+
return t("identity heading");
|
|
2014
|
+
}
|
|
2015
|
+
}, [
|
|
2016
|
+
activeView,
|
|
2017
|
+
t
|
|
2018
|
+
]);
|
|
2019
|
+
const onCancelReset = () => rest.send?.("unchooseAction");
|
|
2020
|
+
const hideRecover = rest.agentStatus !== "created";
|
|
2021
|
+
return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(IdentityHeading, {
|
|
2022
|
+
identity,
|
|
2023
|
+
titleId,
|
|
2024
|
+
title,
|
|
2025
|
+
hideRecover,
|
|
2026
|
+
onDone,
|
|
2027
|
+
onUpdateProfile,
|
|
2028
|
+
connectionState,
|
|
2029
|
+
onChangeConnectionState
|
|
2030
|
+
}), /* @__PURE__ */ React29.createElement(Viewport.Root, {
|
|
2031
|
+
activeView
|
|
2032
|
+
}, /* @__PURE__ */ React29.createElement(Viewport.Views, null, /* @__PURE__ */ React29.createElement(Viewport.View, {
|
|
2033
|
+
id: "identity action chooser",
|
|
2034
|
+
classNames: viewStyles
|
|
2035
|
+
}, /* @__PURE__ */ React29.createElement(IdentityActionChooserComponent, {
|
|
2036
|
+
active: activeView === "identity action chooser",
|
|
2037
|
+
...rest,
|
|
2038
|
+
connectionState
|
|
2039
|
+
})), /* @__PURE__ */ React29.createElement(Viewport.View, {
|
|
2040
|
+
id: "device invitation manager",
|
|
2041
|
+
classNames: viewStyles
|
|
2042
|
+
}, /* @__PURE__ */ React29.createElement(InvitationManagerComponent, {
|
|
2043
|
+
active: activeView === "device invitation manager",
|
|
2044
|
+
...rest,
|
|
2045
|
+
invitationUrl: rest.createInvitationUrl(rest.invitationCode)
|
|
2046
|
+
})), /* @__PURE__ */ React29.createElement(Viewport.View, {
|
|
2047
|
+
classNames: viewStyles,
|
|
2048
|
+
id: "confirm join new identity"
|
|
2049
|
+
}, /* @__PURE__ */ React29.createElement(ConfirmReset, {
|
|
2050
|
+
active: activeView === "confirm join new identity",
|
|
2051
|
+
...rest,
|
|
2052
|
+
mode: "join new identity",
|
|
2053
|
+
onConfirm: onJoinNewIdentity,
|
|
2054
|
+
onCancel: onCancelReset
|
|
2055
|
+
})), /* @__PURE__ */ React29.createElement(Viewport.View, {
|
|
2056
|
+
classNames: viewStyles,
|
|
2057
|
+
id: "confirm recover"
|
|
2058
|
+
}, /* @__PURE__ */ React29.createElement(ConfirmReset, {
|
|
2059
|
+
active: activeView === "confirm recover",
|
|
2060
|
+
...rest,
|
|
2061
|
+
mode: "recover",
|
|
2062
|
+
onConfirm: onRecover,
|
|
2063
|
+
onCancel: onCancelReset
|
|
2064
|
+
})), /* @__PURE__ */ React29.createElement(Viewport.View, {
|
|
2065
|
+
classNames: viewStyles,
|
|
2066
|
+
id: "confirm reset storage"
|
|
2067
|
+
}, /* @__PURE__ */ React29.createElement(ConfirmReset, {
|
|
2068
|
+
active: activeView === "confirm reset storage",
|
|
2069
|
+
...rest,
|
|
2070
|
+
mode: "reset storage",
|
|
2071
|
+
onConfirm: onResetStorage,
|
|
2072
|
+
onCancel: onCancelReset
|
|
2073
|
+
})))));
|
|
2074
|
+
};
|
|
2075
|
+
var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
|
|
2076
|
+
const invitationStatus = useInvitationStatus2(invitation);
|
|
2077
|
+
return /* @__PURE__ */ React29.createElement(IdentityPanelImpl, {
|
|
2078
|
+
...props,
|
|
2079
|
+
...invitationStatus
|
|
2080
|
+
});
|
|
2081
|
+
};
|
|
2082
|
+
var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code, initialDisposition = "default", ...props }) => {
|
|
2083
|
+
const titleId = useId6("identityPanel__heading", propsTitleId);
|
|
2084
|
+
const client = useClient6();
|
|
2085
|
+
const devices = useDevices();
|
|
2086
|
+
const identity = useIdentity();
|
|
2087
|
+
const invitations = useHaloInvitations2();
|
|
2088
|
+
const agentProps = useAgentHandlers({
|
|
2089
|
+
identity,
|
|
2090
|
+
invitations
|
|
2091
|
+
});
|
|
2092
|
+
if (!identity) {
|
|
2093
|
+
log6.error("IdentityPanel rendered with no active identity.", void 0, {
|
|
2094
|
+
F: __dxlog_file6,
|
|
2095
|
+
L: 288,
|
|
2096
|
+
S: void 0,
|
|
2097
|
+
C: (f, a) => f(...a)
|
|
2098
|
+
});
|
|
2099
|
+
return null;
|
|
2100
|
+
}
|
|
2101
|
+
const [identityState, identitySend, identityService] = useIdentityMachine(client, {
|
|
2102
|
+
context: {
|
|
2103
|
+
initialDisposition
|
|
2104
|
+
}
|
|
2105
|
+
});
|
|
2106
|
+
const { swarm: connectionState } = useNetworkStatus();
|
|
2107
|
+
const handleChangeConnectionState = async (nextState) => client?.mesh.updateConfig(nextState);
|
|
2108
|
+
useEffect4(() => {
|
|
2109
|
+
const subscription = identityService.subscribe((state) => {
|
|
2110
|
+
log6("[state]", state, {
|
|
2111
|
+
F: __dxlog_file6,
|
|
2112
|
+
L: 301,
|
|
2113
|
+
S: void 0,
|
|
2114
|
+
C: (f, a) => f(...a)
|
|
2115
|
+
});
|
|
2116
|
+
});
|
|
2117
|
+
return subscription.unsubscribe;
|
|
2118
|
+
}, [
|
|
2119
|
+
identityService
|
|
2120
|
+
]);
|
|
2121
|
+
const activeView = useMemo3(() => {
|
|
2122
|
+
switch (true) {
|
|
2123
|
+
case identityState.matches("choosingAction"):
|
|
2124
|
+
return "identity action chooser";
|
|
2125
|
+
case identityState.matches("managingDeviceInvitation"):
|
|
2126
|
+
return "device invitation manager";
|
|
2127
|
+
case identityState.matches("confirmingResetStorage"):
|
|
2128
|
+
return "confirm reset storage";
|
|
2129
|
+
case identityState.matches("confirmingRecover"):
|
|
2130
|
+
return "confirm recover";
|
|
2131
|
+
case identityState.matches("confirmingJoinNewIdentity"):
|
|
2132
|
+
return "confirm join new identity";
|
|
2133
|
+
default:
|
|
2134
|
+
return "identity action chooser";
|
|
2135
|
+
}
|
|
2136
|
+
}, [
|
|
2137
|
+
identityState
|
|
2138
|
+
]);
|
|
2139
|
+
const onUpdateProfile = async (profile) => {
|
|
2140
|
+
identitySend({
|
|
2141
|
+
type: "updateProfile"
|
|
2142
|
+
});
|
|
2143
|
+
await client.halo.updateProfile(profile);
|
|
2144
|
+
};
|
|
2145
|
+
const implProps = {
|
|
2146
|
+
...props,
|
|
2147
|
+
identity,
|
|
2148
|
+
devices,
|
|
2149
|
+
activeView,
|
|
2150
|
+
send: identitySend,
|
|
2151
|
+
titleId,
|
|
2152
|
+
createInvitationUrl,
|
|
2153
|
+
onUpdateProfile,
|
|
2154
|
+
connectionState,
|
|
2155
|
+
onChangeConnectionState: handleChangeConnectionState,
|
|
2156
|
+
...agentProps
|
|
2157
|
+
};
|
|
2158
|
+
return identityState.context.invitation ? /* @__PURE__ */ React29.createElement(IdentityPanelWithInvitationImpl, {
|
|
2159
|
+
...implProps,
|
|
2160
|
+
invitation: identityState.context.invitation
|
|
2161
|
+
}) : /* @__PURE__ */ React29.createElement(IdentityPanelImpl, implProps);
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
|
|
2165
|
+
import React38, { useCallback as useCallback6, useEffect as useEffect6, useMemo as useMemo4 } from "react";
|
|
2166
|
+
import { log as log10 } from "@dxos/log";
|
|
2167
|
+
import { useClient as useClient8, useMulticastObservable } from "@dxos/react-client";
|
|
2168
|
+
import { useIdentity as useIdentity2 } from "@dxos/react-client/halo";
|
|
2169
|
+
import { useId as useId8, useThemeContext as useThemeContext5 } from "@dxos/react-ui";
|
|
2170
|
+
|
|
2171
|
+
// packages/sdk/shell/src/panels/JoinPanel/JoinHeading.tsx
|
|
2172
|
+
import { X as X4 } from "@phosphor-icons/react";
|
|
2173
|
+
import React30, { cloneElement, forwardRef as forwardRef9 } from "react";
|
|
2174
|
+
import { Button as Button10, useTranslation as useTranslation15 } from "@dxos/react-ui";
|
|
2175
|
+
import { descriptionText as descriptionText9, getSize as getSize14, mx as mx22 } from "@dxos/react-ui-theme";
|
|
2176
|
+
var JoinHeading = /* @__PURE__ */ forwardRef9(({ mode, titleId, exitActionParent, onExit }, forwardedRef) => {
|
|
2177
|
+
const { t } = useTranslation15("os");
|
|
2178
|
+
const exitButton = /* @__PURE__ */ React30.createElement(Button10, {
|
|
2179
|
+
variant: "ghost",
|
|
2180
|
+
...onExit && {
|
|
2181
|
+
onClick: onExit
|
|
2182
|
+
},
|
|
2183
|
+
classNames: mx22(descriptionText9, "plb-0 pli-2 absolute block-start-0 inline-end-0 z-[1]"),
|
|
2184
|
+
"data-testid": "join-exit"
|
|
2185
|
+
}, /* @__PURE__ */ React30.createElement(X4, {
|
|
2186
|
+
weight: "bold",
|
|
2187
|
+
className: getSize14(4)
|
|
2188
|
+
}), /* @__PURE__ */ React30.createElement("span", {
|
|
2189
|
+
className: "sr-only"
|
|
2190
|
+
}, t("exit label")));
|
|
2191
|
+
return /* @__PURE__ */ React30.createElement(Heading, {
|
|
2192
|
+
ref: forwardedRef,
|
|
2193
|
+
titleId,
|
|
2194
|
+
title: t(mode === "halo-only" ? "selecting identity heading" : "joining space heading"),
|
|
2195
|
+
...mode === "halo-only" ? {
|
|
2196
|
+
titleSrOnly: true
|
|
2197
|
+
} : {
|
|
2198
|
+
corner: exitActionParent ? /* @__PURE__ */ cloneElement(exitActionParent, {}, exitButton) : exitButton
|
|
2199
|
+
},
|
|
2200
|
+
titleSrOnly: mode === "halo-only"
|
|
2201
|
+
});
|
|
2202
|
+
});
|
|
2203
|
+
|
|
2204
|
+
// packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts
|
|
2205
|
+
import { useMachine as useMachine2 } from "@xstate/react";
|
|
2206
|
+
import { useCallback as useCallback5 } from "react";
|
|
2207
|
+
import { assign as assign2, createMachine as createMachine2 } from "xstate";
|
|
2208
|
+
import { log as log7 } from "@dxos/log";
|
|
2209
|
+
import { AlreadyJoinedError } from "@dxos/react-client";
|
|
2210
|
+
import { Invitation as Invitation5, InvitationEncoder as InvitationEncoder3 } from "@dxos/react-client/invitations";
|
|
2211
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts";
|
|
2212
|
+
var getInvitationSubscribable = (Kind, invitation) => {
|
|
2213
|
+
log7("[subscribing to invitation]", invitation, {
|
|
2214
|
+
F: __dxlog_file7,
|
|
2215
|
+
L: 90,
|
|
2216
|
+
S: void 0,
|
|
2217
|
+
C: (f, a) => f(...a)
|
|
2218
|
+
});
|
|
2219
|
+
return {
|
|
2220
|
+
subscribe: (next, onError, complete) => invitation.subscribe((invitation2) => {
|
|
2221
|
+
switch (invitation2.state) {
|
|
2222
|
+
case Invitation5.State.CONNECTING: {
|
|
2223
|
+
log7("[invitation connecting]", {
|
|
2224
|
+
Kind,
|
|
2225
|
+
invitation: invitation2
|
|
2226
|
+
}, {
|
|
2227
|
+
F: __dxlog_file7,
|
|
2228
|
+
L: 101,
|
|
2229
|
+
S: void 0,
|
|
2230
|
+
C: (f, a) => f(...a)
|
|
2231
|
+
});
|
|
2232
|
+
return next({
|
|
2233
|
+
type: `connecting${Kind}Invitation`,
|
|
2234
|
+
invitation: invitation2
|
|
2235
|
+
});
|
|
2236
|
+
}
|
|
2237
|
+
case Invitation5.State.CONNECTED: {
|
|
2238
|
+
log7("[invitation connected]", {
|
|
2239
|
+
Kind,
|
|
2240
|
+
invitation: invitation2
|
|
2241
|
+
}, {
|
|
2242
|
+
F: __dxlog_file7,
|
|
2243
|
+
L: 106,
|
|
2244
|
+
S: void 0,
|
|
2245
|
+
C: (f, a) => f(...a)
|
|
2246
|
+
});
|
|
2247
|
+
return next({
|
|
2248
|
+
type: `connected${Kind}Invitation`,
|
|
2249
|
+
invitation: invitation2
|
|
2250
|
+
});
|
|
2251
|
+
}
|
|
2252
|
+
case Invitation5.State.READY_FOR_AUTHENTICATION: {
|
|
2253
|
+
log7("[invitation ready for authentication]", {
|
|
2254
|
+
Kind,
|
|
2255
|
+
invitation: invitation2
|
|
2256
|
+
}, {
|
|
2257
|
+
F: __dxlog_file7,
|
|
2258
|
+
L: 111,
|
|
2259
|
+
S: void 0,
|
|
2260
|
+
C: (f, a) => f(...a)
|
|
2261
|
+
});
|
|
2262
|
+
return next({
|
|
2263
|
+
type: `readyForAuthentication${Kind}Invitation`,
|
|
2264
|
+
invitation: invitation2
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
case Invitation5.State.AUTHENTICATING: {
|
|
2268
|
+
log7("[invitation authenticating]", {
|
|
2269
|
+
Kind,
|
|
2270
|
+
invitation: invitation2
|
|
2271
|
+
}, {
|
|
2272
|
+
F: __dxlog_file7,
|
|
2273
|
+
L: 116,
|
|
2274
|
+
S: void 0,
|
|
2275
|
+
C: (f, a) => f(...a)
|
|
2276
|
+
});
|
|
2277
|
+
return next({
|
|
2278
|
+
type: `authenticating${Kind}Invitation`,
|
|
2279
|
+
invitation: invitation2
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
case Invitation5.State.SUCCESS: {
|
|
2283
|
+
log7("[invitation success]", {
|
|
2284
|
+
Kind,
|
|
2285
|
+
invitation: invitation2
|
|
2286
|
+
}, {
|
|
2287
|
+
F: __dxlog_file7,
|
|
2288
|
+
L: 121,
|
|
2289
|
+
S: void 0,
|
|
2290
|
+
C: (f, a) => f(...a)
|
|
2291
|
+
});
|
|
2292
|
+
next({
|
|
2293
|
+
type: `success${Kind}Invitation`,
|
|
2294
|
+
invitation: invitation2
|
|
2295
|
+
});
|
|
2296
|
+
return complete?.();
|
|
2297
|
+
}
|
|
2298
|
+
case Invitation5.State.CANCELLED: {
|
|
2299
|
+
log7.warn("[invitation cancelled]", {
|
|
2300
|
+
Kind
|
|
2301
|
+
}, {
|
|
2302
|
+
F: __dxlog_file7,
|
|
2303
|
+
L: 127,
|
|
2304
|
+
S: void 0,
|
|
2305
|
+
C: (f, a) => f(...a)
|
|
2306
|
+
});
|
|
2307
|
+
return next({
|
|
2308
|
+
type: `fail${Kind}Invitation`,
|
|
2309
|
+
reason: "cancelled"
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
case Invitation5.State.TIMEOUT: {
|
|
2313
|
+
log7.error("[invitation timeout]", {
|
|
2314
|
+
Kind
|
|
2315
|
+
}, {
|
|
2316
|
+
F: __dxlog_file7,
|
|
2317
|
+
L: 132,
|
|
2318
|
+
S: void 0,
|
|
2319
|
+
C: (f, a) => f(...a)
|
|
2320
|
+
});
|
|
2321
|
+
return next({
|
|
2322
|
+
type: `fail${Kind}Invitation`,
|
|
2323
|
+
reason: "timeout"
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
}, (error) => {
|
|
2328
|
+
if (error instanceof AlreadyJoinedError) {
|
|
2329
|
+
log7("[already joined]", {
|
|
2330
|
+
Kind,
|
|
2331
|
+
error
|
|
2332
|
+
}, {
|
|
2333
|
+
F: __dxlog_file7,
|
|
2334
|
+
L: 139,
|
|
2335
|
+
S: void 0,
|
|
2336
|
+
C: (f, a) => f(...a)
|
|
2337
|
+
});
|
|
2338
|
+
next({
|
|
2339
|
+
type: `success${Kind}Invitation`,
|
|
2340
|
+
invitation: invitation.get()
|
|
2341
|
+
});
|
|
2342
|
+
return complete?.();
|
|
2343
|
+
}
|
|
2344
|
+
log7.error("[invitation errored]", {
|
|
2345
|
+
Kind,
|
|
2346
|
+
error
|
|
2347
|
+
}, {
|
|
2348
|
+
F: __dxlog_file7,
|
|
2349
|
+
L: 144,
|
|
2350
|
+
S: void 0,
|
|
2351
|
+
C: (f, a) => f(...a)
|
|
2352
|
+
});
|
|
2353
|
+
next({
|
|
2354
|
+
type: `fail${Kind}Invitation`,
|
|
2355
|
+
reason: "error"
|
|
2356
|
+
});
|
|
2357
|
+
return onError?.(error);
|
|
2358
|
+
})
|
|
2359
|
+
};
|
|
2360
|
+
};
|
|
2361
|
+
var acceptingInvitationTemplate = (Kind, successTarget) => {
|
|
2362
|
+
const config = {
|
|
2363
|
+
initial: `unknown${Kind}`,
|
|
2364
|
+
states: {
|
|
2365
|
+
[`unknown${Kind}`]: {
|
|
2366
|
+
always: [
|
|
2367
|
+
{
|
|
2368
|
+
cond: ({ mode }) => mode === "halo-only" && Kind === "Space",
|
|
2369
|
+
target: "#join.finishingJoiningHalo"
|
|
2370
|
+
},
|
|
2371
|
+
{
|
|
2372
|
+
cond: (context) => !!context[Kind.toLowerCase()].unredeemedCode,
|
|
2373
|
+
target: `acceptingRedeemed${Kind}Invitation`,
|
|
2374
|
+
actions: [
|
|
2375
|
+
`redeem${Kind}InvitationCode`,
|
|
2376
|
+
`invalidate${Kind}InvitationCode`,
|
|
2377
|
+
"log"
|
|
2378
|
+
]
|
|
2379
|
+
},
|
|
2380
|
+
{
|
|
2381
|
+
target: `inputting${Kind}InvitationCode`,
|
|
2382
|
+
actions: "log"
|
|
2383
|
+
}
|
|
2384
|
+
]
|
|
2385
|
+
},
|
|
2386
|
+
[`inputting${Kind}InvitationCode`]: {},
|
|
2387
|
+
[`acceptingRedeemed${Kind}Invitation`]: {
|
|
2388
|
+
invoke: {
|
|
2389
|
+
src: (context) => context[Kind.toLowerCase()].invitationSubscribable
|
|
2390
|
+
},
|
|
2391
|
+
initial: `unknown${Kind}Invitation`,
|
|
2392
|
+
states: {
|
|
2393
|
+
[`unknown${Kind}Invitation`]: {
|
|
2394
|
+
always: [
|
|
2395
|
+
{
|
|
2396
|
+
cond: (context) => {
|
|
2397
|
+
if (Kind !== "Space") {
|
|
2398
|
+
return false;
|
|
2399
|
+
} else {
|
|
2400
|
+
const spaceKey = context.space.invitation?.spaceKey?.toHex();
|
|
2401
|
+
const succeededKeys = context.space.succeededKeys;
|
|
2402
|
+
return spaceKey ? !!succeededKeys?.has(spaceKey) : false;
|
|
2403
|
+
}
|
|
2404
|
+
},
|
|
2405
|
+
target: successTarget,
|
|
2406
|
+
actions: "log"
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
cond: (context) => {
|
|
2410
|
+
const invitation = context[Kind.toLowerCase()].invitation;
|
|
2411
|
+
return !invitation || invitation?.state === Invitation5.State.CONNECTING;
|
|
2412
|
+
},
|
|
2413
|
+
target: `connecting${Kind}Invitation`,
|
|
2414
|
+
actions: "log"
|
|
2415
|
+
},
|
|
2416
|
+
{
|
|
2417
|
+
target: `inputting${Kind}VerificationCode`,
|
|
2418
|
+
actions: "log"
|
|
2419
|
+
}
|
|
2420
|
+
]
|
|
2421
|
+
},
|
|
2422
|
+
[`connecting${Kind}Invitation`]: {},
|
|
2423
|
+
[`inputting${Kind}VerificationCode`]: {},
|
|
2424
|
+
[`authenticating${Kind}VerificationCode`]: {
|
|
2425
|
+
on: {
|
|
2426
|
+
[`readyForAuthentication${Kind}Invitation`]: {
|
|
2427
|
+
target: `authenticationFailing${Kind}VerificationCode`,
|
|
2428
|
+
actions: [
|
|
2429
|
+
"setInvitation",
|
|
2430
|
+
"log"
|
|
2431
|
+
]
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
},
|
|
2435
|
+
[`authenticationFailing${Kind}VerificationCode`]: {},
|
|
2436
|
+
[`failing${Kind}Invitation`]: {},
|
|
2437
|
+
[`success${Kind}Invitation`]: {}
|
|
2438
|
+
},
|
|
2439
|
+
on: {
|
|
2440
|
+
[`reset${Kind}Invitation`]: {
|
|
2441
|
+
target: `#join${Kind === "Halo" ? ".choosingIdentity" : ""}.accepting${Kind}Invitation.unknown${Kind}`,
|
|
2442
|
+
actions: [
|
|
2443
|
+
"resetInvitation",
|
|
2444
|
+
"log"
|
|
2445
|
+
]
|
|
2446
|
+
},
|
|
2447
|
+
[`connecting${Kind}Invitation`]: {
|
|
2448
|
+
target: `.connecting${Kind}Invitation`,
|
|
2449
|
+
actions: [
|
|
2450
|
+
"setInvitation",
|
|
2451
|
+
"log"
|
|
2452
|
+
]
|
|
2453
|
+
},
|
|
2454
|
+
[`connected${Kind}Invitation`]: {
|
|
2455
|
+
target: `.connecting${Kind}Invitation`,
|
|
2456
|
+
actions: [
|
|
2457
|
+
"setInvitation",
|
|
2458
|
+
"log"
|
|
2459
|
+
]
|
|
2460
|
+
},
|
|
2461
|
+
[`readyForAuthentication${Kind}Invitation`]: {
|
|
2462
|
+
target: `.inputting${Kind}VerificationCode`,
|
|
2463
|
+
actions: [
|
|
2464
|
+
"setInvitation",
|
|
2465
|
+
"log"
|
|
2466
|
+
]
|
|
2467
|
+
},
|
|
2468
|
+
[`authenticating${Kind}Invitation`]: {
|
|
2469
|
+
target: `.authenticating${Kind}VerificationCode`,
|
|
2470
|
+
actions: [
|
|
2471
|
+
"setInvitation",
|
|
2472
|
+
"log"
|
|
2473
|
+
]
|
|
2474
|
+
},
|
|
2475
|
+
[`success${Kind}Invitation`]: {
|
|
2476
|
+
target: successTarget,
|
|
2477
|
+
actions: [
|
|
2478
|
+
"setInvitation",
|
|
2479
|
+
"log"
|
|
2480
|
+
]
|
|
2481
|
+
},
|
|
2482
|
+
[`fail${Kind}Invitation`]: {
|
|
2483
|
+
target: `.failing${Kind}Invitation`,
|
|
2484
|
+
actions: [
|
|
2485
|
+
assign2({
|
|
2486
|
+
[Kind.toLowerCase()]: (context, event) => ({
|
|
2487
|
+
...context[Kind.toLowerCase()],
|
|
2488
|
+
failReason: event.reason
|
|
2489
|
+
})
|
|
2490
|
+
}),
|
|
2491
|
+
"log"
|
|
2492
|
+
]
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
},
|
|
2497
|
+
on: {
|
|
2498
|
+
[`set${Kind}InvitationCode`]: {
|
|
2499
|
+
target: `.acceptingRedeemed${Kind}Invitation`,
|
|
2500
|
+
actions: [
|
|
2501
|
+
assign2({
|
|
2502
|
+
[Kind.toLowerCase()]: (context, event) => ({
|
|
2503
|
+
...context[Kind.toLowerCase()],
|
|
2504
|
+
unredeemedCode: event.code,
|
|
2505
|
+
succeededKeys: event.succeededKeys
|
|
2506
|
+
})
|
|
2507
|
+
}),
|
|
2508
|
+
`redeem${Kind}InvitationCode`,
|
|
2509
|
+
`invalidate${Kind}InvitationCode`,
|
|
2510
|
+
"log"
|
|
2511
|
+
]
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
};
|
|
2515
|
+
return config;
|
|
2516
|
+
};
|
|
2517
|
+
var joinMachine = createMachine2({
|
|
2518
|
+
id: "join",
|
|
2519
|
+
predictableActionArguments: true,
|
|
2520
|
+
context: {
|
|
2521
|
+
initialDisposition: "default",
|
|
2522
|
+
mode: "default",
|
|
2523
|
+
identity: null,
|
|
2524
|
+
halo: {},
|
|
2525
|
+
space: {}
|
|
2526
|
+
},
|
|
2527
|
+
initial: "unknown",
|
|
2528
|
+
states: {
|
|
2529
|
+
unknown: {
|
|
2530
|
+
always: [
|
|
2531
|
+
{
|
|
2532
|
+
cond: "existingIdentity",
|
|
2533
|
+
target: "resettingIdentity",
|
|
2534
|
+
actions: "log"
|
|
2535
|
+
},
|
|
2536
|
+
{
|
|
2537
|
+
cond: "initiallyAcceptingHaloInvitation",
|
|
2538
|
+
target: "#join.choosingIdentity.acceptingHaloInvitation",
|
|
2539
|
+
actions: "log"
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
cond: "initiallyRecoveringIdentity",
|
|
2543
|
+
target: "#join.choosingIdentity.recoveringIdentity",
|
|
2544
|
+
actions: "log"
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
cond: "noSelectedIdentity",
|
|
2548
|
+
target: "choosingIdentity",
|
|
2549
|
+
actions: "log"
|
|
2550
|
+
},
|
|
2551
|
+
{
|
|
2552
|
+
target: "acceptingSpaceInvitation",
|
|
2553
|
+
actions: "log"
|
|
2554
|
+
}
|
|
2555
|
+
]
|
|
2556
|
+
},
|
|
2557
|
+
// TODO(wittjosiah): Remove.
|
|
2558
|
+
choosingIdentity: {
|
|
2559
|
+
initial: "unknownAuthMethod",
|
|
2560
|
+
states: {
|
|
2561
|
+
unknownAuthMethod: {
|
|
2562
|
+
always: [
|
|
2563
|
+
{
|
|
2564
|
+
cond: "hasHaloUnredeemedCode",
|
|
2565
|
+
target: "acceptingHaloInvitation",
|
|
2566
|
+
actions: "log"
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
target: "choosingAuthMethod",
|
|
2570
|
+
actions: "log"
|
|
2571
|
+
}
|
|
2572
|
+
]
|
|
2573
|
+
},
|
|
2574
|
+
choosingAuthMethod: {},
|
|
2575
|
+
recoveringIdentity: {},
|
|
2576
|
+
creatingIdentity: {},
|
|
2577
|
+
acceptingHaloInvitation: acceptingInvitationTemplate("Halo", "#join.acceptingSpaceInvitation"),
|
|
2578
|
+
confirmingAddedIdentity: {}
|
|
2579
|
+
},
|
|
2580
|
+
on: {
|
|
2581
|
+
recoverIdentity: {
|
|
2582
|
+
target: ".recoveringIdentity",
|
|
2583
|
+
actions: "log"
|
|
2584
|
+
},
|
|
2585
|
+
createIdentity: {
|
|
2586
|
+
target: ".creatingIdentity",
|
|
2587
|
+
actions: "log"
|
|
2588
|
+
},
|
|
2589
|
+
acceptHaloInvitation: {
|
|
2590
|
+
target: ".acceptingHaloInvitation",
|
|
2591
|
+
actions: "log"
|
|
2592
|
+
},
|
|
2593
|
+
addIdentity: {
|
|
2594
|
+
target: ".confirmingAddedIdentity",
|
|
2595
|
+
actions: "log"
|
|
2596
|
+
},
|
|
2597
|
+
selectIdentity: {
|
|
2598
|
+
target: "acceptingSpaceInvitation",
|
|
2599
|
+
actions: [
|
|
2600
|
+
"setIdentity",
|
|
2601
|
+
"log"
|
|
2602
|
+
]
|
|
2603
|
+
},
|
|
2604
|
+
deselectAuthMethod: {
|
|
2605
|
+
target: ".choosingAuthMethod",
|
|
2606
|
+
actions: "log"
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
},
|
|
2610
|
+
// TODO(wittjosiah): Factor out to a machine handling recovery and device invitations.
|
|
2611
|
+
resettingIdentity: {},
|
|
2612
|
+
acceptingSpaceInvitation: acceptingInvitationTemplate("Space", "#join.finishingJoiningSpace"),
|
|
2613
|
+
finishingJoiningSpace: {
|
|
2614
|
+
type: "final"
|
|
2615
|
+
},
|
|
2616
|
+
finishingJoiningHalo: {
|
|
2617
|
+
type: "final"
|
|
2618
|
+
}
|
|
2619
|
+
},
|
|
2620
|
+
on: {
|
|
2621
|
+
resetIdentity: {
|
|
2622
|
+
target: "choosingIdentity",
|
|
2623
|
+
actions: "unsetIdentity"
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
}, {
|
|
2627
|
+
guards: {
|
|
2628
|
+
existingIdentity: ({ identity, mode }, _event) => mode === "halo-only" && !!identity,
|
|
2629
|
+
noSelectedIdentity: ({ identity }, _event) => !identity,
|
|
2630
|
+
initiallyAcceptingHaloInvitation: ({ identity, initialDisposition }, _event) => !identity && initialDisposition === "accept-halo-invitation",
|
|
2631
|
+
initiallyRecoveringIdentity: ({ identity, initialDisposition }, _event) => !identity && initialDisposition === "recover-identity",
|
|
2632
|
+
hasHaloUnredeemedCode: ({ halo }, _event) => !!halo.unredeemedCode,
|
|
2633
|
+
noSpaceInvitation: ({ space }, _event) => !space.invitation && !space.unredeemedCode
|
|
2634
|
+
},
|
|
2635
|
+
actions: {
|
|
2636
|
+
setIdentity: assign2({
|
|
2637
|
+
identity: (context, event) => event.identity
|
|
2638
|
+
}),
|
|
2639
|
+
unsetIdentity: assign2({
|
|
2640
|
+
identity: () => null
|
|
2641
|
+
}),
|
|
2642
|
+
resetInvitation: assign2({
|
|
2643
|
+
halo: (context, event) => {
|
|
2644
|
+
if (event.type !== "resetHaloInvitation") {
|
|
2645
|
+
return context.halo;
|
|
2646
|
+
}
|
|
2647
|
+
if (context.halo.invitationObservable) {
|
|
2648
|
+
void context.halo.invitationObservable.cancel();
|
|
2649
|
+
}
|
|
2650
|
+
return {
|
|
2651
|
+
...context.halo,
|
|
2652
|
+
invitation: void 0,
|
|
2653
|
+
invitationObservable: void 0,
|
|
2654
|
+
invitationSubscribable: void 0
|
|
2655
|
+
};
|
|
2656
|
+
},
|
|
2657
|
+
space: (context, event) => {
|
|
2658
|
+
if (event.type !== "resetSpaceInvitation") {
|
|
2659
|
+
return context.space;
|
|
2660
|
+
}
|
|
2661
|
+
if (context.space.invitationObservable) {
|
|
2662
|
+
void context.space.invitationObservable.cancel();
|
|
2663
|
+
}
|
|
2664
|
+
return {
|
|
2665
|
+
...context.space,
|
|
2666
|
+
invitation: void 0,
|
|
2667
|
+
invitationObservable: void 0,
|
|
2668
|
+
invitationSubscribable: void 0
|
|
2669
|
+
};
|
|
2670
|
+
}
|
|
2671
|
+
}),
|
|
2672
|
+
setInvitation: assign2({
|
|
2673
|
+
halo: (context, event) => event.type.includes("Halo") ? {
|
|
2674
|
+
...context.halo,
|
|
2675
|
+
invitation: event.invitation
|
|
2676
|
+
} : context.halo,
|
|
2677
|
+
space: (context, event) => event.type.includes("Space") ? {
|
|
2678
|
+
...context.space,
|
|
2679
|
+
invitation: event.invitation
|
|
2680
|
+
} : context.space
|
|
2681
|
+
}),
|
|
2682
|
+
log: (context, event) => {
|
|
2683
|
+
log7("[transition]", {
|
|
2684
|
+
event,
|
|
2685
|
+
haloInvitation: context.halo.invitation,
|
|
2686
|
+
spaceInvitation: context.space.invitation
|
|
2687
|
+
}, {
|
|
2688
|
+
F: __dxlog_file7,
|
|
2689
|
+
L: 425,
|
|
2690
|
+
S: void 0,
|
|
2691
|
+
C: (f, a) => f(...a)
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
});
|
|
2696
|
+
var defaultCodeFromUrl = (invitationType, text) => {
|
|
2697
|
+
try {
|
|
2698
|
+
const searchParams = new URLSearchParams(text.substring(text.lastIndexOf("?")));
|
|
2699
|
+
return searchParams.get(`${invitationType}InvitationCode`) ?? searchParams.get(`${invitationType}Invitation`) ?? searchParams.get("invitationCode") ?? searchParams.get("invitation") ?? text;
|
|
2700
|
+
} catch (err) {
|
|
2701
|
+
log7.catch(err, void 0, {
|
|
2702
|
+
F: __dxlog_file7,
|
|
2703
|
+
L: 452,
|
|
2704
|
+
S: void 0,
|
|
2705
|
+
C: (f, a) => f(...a)
|
|
2706
|
+
});
|
|
2707
|
+
return text;
|
|
2708
|
+
}
|
|
2709
|
+
};
|
|
2710
|
+
var useJoinMachine = (client, options) => {
|
|
2711
|
+
const redeemHaloInvitationCode = useCallback5(({ halo }) => {
|
|
2712
|
+
if (halo.unredeemedCode) {
|
|
2713
|
+
try {
|
|
2714
|
+
const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode));
|
|
2715
|
+
const invitationObservable = client.halo.join(invitation);
|
|
2716
|
+
return {
|
|
2717
|
+
...halo,
|
|
2718
|
+
invitationObservable,
|
|
2719
|
+
invitationSubscribable: getInvitationSubscribable("Halo", invitationObservable)
|
|
2720
|
+
};
|
|
2721
|
+
} catch (err) {
|
|
2722
|
+
log7.error("Could not redeem device invitation code", err, {
|
|
2723
|
+
F: __dxlog_file7,
|
|
2724
|
+
L: 473,
|
|
2725
|
+
S: void 0,
|
|
2726
|
+
C: (f, a) => f(...a)
|
|
2727
|
+
});
|
|
2728
|
+
return halo;
|
|
2729
|
+
}
|
|
2730
|
+
} else {
|
|
2731
|
+
return halo;
|
|
2732
|
+
}
|
|
2733
|
+
}, [
|
|
2734
|
+
client
|
|
2735
|
+
]);
|
|
2736
|
+
const redeemSpaceInvitationCode = useCallback5(({ space }) => {
|
|
2737
|
+
if (space.unredeemedCode) {
|
|
2738
|
+
try {
|
|
2739
|
+
const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("space", space.unredeemedCode));
|
|
2740
|
+
const invitationObservable = client.spaces.join(invitation);
|
|
2741
|
+
return {
|
|
2742
|
+
...space,
|
|
2743
|
+
invitationObservable,
|
|
2744
|
+
invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
|
|
2745
|
+
};
|
|
2746
|
+
} catch (err) {
|
|
2747
|
+
log7.error("Could not redeem space invitation code", err, {
|
|
2748
|
+
F: __dxlog_file7,
|
|
2749
|
+
L: 495,
|
|
2750
|
+
S: void 0,
|
|
2751
|
+
C: (f, a) => f(...a)
|
|
2752
|
+
});
|
|
2753
|
+
return space;
|
|
2754
|
+
}
|
|
2755
|
+
} else {
|
|
2756
|
+
return space;
|
|
2757
|
+
}
|
|
2758
|
+
}, [
|
|
2759
|
+
client
|
|
2760
|
+
]);
|
|
2761
|
+
const invalidateHaloInvitationCode = useCallback5(({ halo }) => {
|
|
2762
|
+
if (halo.unredeemedCode) {
|
|
2763
|
+
options?.onInvalidateInvitationCode?.(halo.unredeemedCode);
|
|
2764
|
+
return {
|
|
2765
|
+
...halo,
|
|
2766
|
+
unredeemedCode: void 0
|
|
2767
|
+
};
|
|
2768
|
+
} else {
|
|
2769
|
+
return halo;
|
|
2770
|
+
}
|
|
2771
|
+
}, [
|
|
2772
|
+
options?.onInvalidateInvitationCode
|
|
2773
|
+
]);
|
|
2774
|
+
const invalidateSpaceInvitationCode = useCallback5(({ space }) => {
|
|
2775
|
+
if (space.unredeemedCode) {
|
|
2776
|
+
options?.onInvalidateInvitationCode?.(space.unredeemedCode);
|
|
2777
|
+
return {
|
|
2778
|
+
...space,
|
|
2779
|
+
unredeemedCode: void 0
|
|
2780
|
+
};
|
|
2781
|
+
} else {
|
|
2782
|
+
return space;
|
|
2783
|
+
}
|
|
2784
|
+
}, [
|
|
2785
|
+
options?.onInvalidateInvitationCode
|
|
2786
|
+
]);
|
|
2787
|
+
return useMachine2(joinMachine, {
|
|
2788
|
+
...options,
|
|
2789
|
+
actions: {
|
|
2790
|
+
...options?.actions,
|
|
2791
|
+
redeemHaloInvitationCode: assign2({
|
|
2792
|
+
halo: redeemHaloInvitationCode
|
|
2793
|
+
}),
|
|
2794
|
+
redeemSpaceInvitationCode: assign2({
|
|
2795
|
+
space: redeemSpaceInvitationCode
|
|
2796
|
+
}),
|
|
2797
|
+
invalidateHaloInvitationCode: assign2({
|
|
2798
|
+
halo: invalidateHaloInvitationCode
|
|
2799
|
+
}),
|
|
2800
|
+
invalidateSpaceInvitationCode: assign2({
|
|
2801
|
+
space: invalidateSpaceInvitationCode
|
|
2802
|
+
})
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
2805
|
+
};
|
|
2806
|
+
|
|
2807
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx
|
|
2808
|
+
import { CaretRight as CaretRight2, Plus as Plus3, QrCode, Textbox } from "@phosphor-icons/react";
|
|
2809
|
+
import React31 from "react";
|
|
2810
|
+
import { useTranslation as useTranslation16 } from "@dxos/react-ui";
|
|
2811
|
+
import { getSize as getSize15 } from "@dxos/react-ui-theme";
|
|
2812
|
+
var AdditionMethodChooser = (viewStateProps) => {
|
|
2813
|
+
const disabled = !viewStateProps.active;
|
|
2814
|
+
const { send } = viewStateProps;
|
|
2815
|
+
const { t } = useTranslation16("os");
|
|
2816
|
+
const sharedButtonProps = {
|
|
2817
|
+
disabled,
|
|
2818
|
+
after: /* @__PURE__ */ React31.createElement(CaretRight2, {
|
|
2819
|
+
className: getSize15(4),
|
|
2820
|
+
weight: "bold"
|
|
2821
|
+
}),
|
|
2822
|
+
slots: {
|
|
2823
|
+
label: {
|
|
2824
|
+
className: "text-sm"
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
};
|
|
2828
|
+
return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(StepHeading, null, t("addition method chooser title")), /* @__PURE__ */ React31.createElement("div", {
|
|
2829
|
+
role: "none",
|
|
2830
|
+
className: "flex flex-col gap-1 grow"
|
|
2831
|
+
}, /* @__PURE__ */ React31.createElement(CompoundButton, {
|
|
2832
|
+
...sharedButtonProps,
|
|
2833
|
+
description: t("create identity description"),
|
|
2834
|
+
before: /* @__PURE__ */ React31.createElement(Plus3, {
|
|
2835
|
+
className: getSize15(6)
|
|
2836
|
+
}),
|
|
2837
|
+
onClick: () => send({
|
|
2838
|
+
type: "createIdentity"
|
|
2839
|
+
}),
|
|
2840
|
+
"data-autofocus": "choosingAuthMethod",
|
|
2841
|
+
"data-testid": "identity-chooser.create-identity"
|
|
2842
|
+
}, t("create identity label")), /* @__PURE__ */ React31.createElement(CompoundButton, {
|
|
2843
|
+
...sharedButtonProps,
|
|
2844
|
+
description: t("join identity description"),
|
|
2845
|
+
before: /* @__PURE__ */ React31.createElement(QrCode, {
|
|
2846
|
+
className: getSize15(6)
|
|
2847
|
+
}),
|
|
2848
|
+
onClick: () => send({
|
|
2849
|
+
type: "acceptHaloInvitation"
|
|
2850
|
+
}),
|
|
2851
|
+
"data-testid": "identity-chooser.join-identity"
|
|
2852
|
+
}, t("join identity label")), /* @__PURE__ */ React31.createElement(CompoundButton, {
|
|
2853
|
+
...sharedButtonProps,
|
|
2854
|
+
description: t("recover identity description"),
|
|
2855
|
+
before: /* @__PURE__ */ React31.createElement(Textbox, {
|
|
2856
|
+
className: getSize15(6)
|
|
2857
|
+
}),
|
|
2858
|
+
onClick: () => send({
|
|
2859
|
+
type: "recoverIdentity"
|
|
2860
|
+
}),
|
|
2861
|
+
"data-testid": "identity-chooser.recover-identity"
|
|
2862
|
+
}, t("recover identity label"))));
|
|
2863
|
+
};
|
|
2864
|
+
|
|
2865
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/IdentityAdded.tsx
|
|
2866
|
+
import React32, { cloneElement as cloneElement2 } from "react";
|
|
2867
|
+
import { generateName as generateName4 } from "@dxos/display-name";
|
|
2868
|
+
import { Avatar as Avatar7, useId as useId7, useTranslation as useTranslation17 } from "@dxos/react-ui";
|
|
2869
|
+
import { mx as mx23 } from "@dxos/react-ui-theme";
|
|
2870
|
+
import { hexToFallback } from "@dxos/util";
|
|
2871
|
+
var IdentityAdded = (props) => {
|
|
2872
|
+
const { mode, addedIdentity, active, send, onDone, doneActionParent } = props;
|
|
2873
|
+
const disabled = !active;
|
|
2874
|
+
const { t } = useTranslation17("os");
|
|
2875
|
+
const addedIdentityHex = addedIdentity?.identityKey.toHex() ?? "0";
|
|
2876
|
+
const fallbackValue = hexToFallback(addedIdentityHex);
|
|
2877
|
+
const labelId = useId7("identityListItem__label");
|
|
2878
|
+
const displayName = addedIdentity?.profile?.displayName ?? (addedIdentity && generateName4(addedIdentityHex));
|
|
2879
|
+
const doneAction = /* @__PURE__ */ React32.createElement(Action, {
|
|
2880
|
+
...onDone && {
|
|
2881
|
+
onClick: () => onDone(null)
|
|
2882
|
+
},
|
|
2883
|
+
disabled,
|
|
2884
|
+
"data-autofocus": "confirmingAddedIdentity",
|
|
2885
|
+
"data-testid": "identity-added-done"
|
|
2886
|
+
}, /* @__PURE__ */ React32.createElement("span", null, t("done label")));
|
|
2887
|
+
return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(StepHeading, null, t("identity added label")), /* @__PURE__ */ React32.createElement("div", {
|
|
2888
|
+
role: "none",
|
|
2889
|
+
className: "grow flex flex-col items-center justify-center text-center gap-2"
|
|
2890
|
+
}, /* @__PURE__ */ React32.createElement(Avatar7.Root, {
|
|
2891
|
+
status: "active",
|
|
2892
|
+
labelId,
|
|
2893
|
+
hue: addedIdentity?.profile?.data?.hue || fallbackValue.hue
|
|
2894
|
+
}, /* @__PURE__ */ React32.createElement(Avatar7.Frame, null, /* @__PURE__ */ React32.createElement(Avatar7.Fallback, {
|
|
2895
|
+
text: addedIdentity?.profile?.data?.emoji || fallbackValue.emoji
|
|
2896
|
+
})), /* @__PURE__ */ React32.createElement(Avatar7.Label, {
|
|
2897
|
+
classNames: mx23("text-lg truncate", !addedIdentity?.profile?.displayName && "font-mono")
|
|
2898
|
+
}, displayName))), /* @__PURE__ */ React32.createElement(Actions, null, mode === "halo-only" ? doneActionParent ? /* @__PURE__ */ cloneElement2(doneActionParent, {}, doneAction) : doneAction : /* @__PURE__ */ React32.createElement(Action, {
|
|
2899
|
+
variant: "primary",
|
|
2900
|
+
disabled: disabled || !addedIdentity,
|
|
2901
|
+
onClick: () => addedIdentity && send({
|
|
2902
|
+
type: "selectIdentity",
|
|
2903
|
+
identity: addedIdentity
|
|
2904
|
+
}),
|
|
2905
|
+
"data-autofocus": "confirmingAddedIdentity"
|
|
2906
|
+
}, t("continue label"))));
|
|
2907
|
+
};
|
|
2908
|
+
|
|
2909
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx
|
|
2910
|
+
import React33, { useState as useState10 } from "react";
|
|
2911
|
+
import { log as log8 } from "@dxos/log";
|
|
2912
|
+
import { useClient as useClient7 } from "@dxos/react-client";
|
|
2913
|
+
import { useTranslation as useTranslation18 } from "@dxos/react-ui";
|
|
2914
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx";
|
|
2915
|
+
var IdentityInput = (props) => {
|
|
2916
|
+
const { send, method } = props;
|
|
2917
|
+
const isRecover = method === "recover identity";
|
|
2918
|
+
const client = useClient7();
|
|
2919
|
+
const { t } = useTranslation18("os");
|
|
2920
|
+
const [validationMessage, setValidationMessage] = useState10("");
|
|
2921
|
+
const createIdentity = (value) => {
|
|
2922
|
+
if (isRecover) {
|
|
2923
|
+
void client.halo.recoverIdentity({
|
|
2924
|
+
seedphrase: value
|
|
2925
|
+
}).then((identity) => {
|
|
2926
|
+
send?.({
|
|
2927
|
+
type: "selectIdentity",
|
|
2928
|
+
identity
|
|
2929
|
+
});
|
|
2930
|
+
}, (error) => {
|
|
2931
|
+
log8.catch(error, void 0, {
|
|
2932
|
+
F: __dxlog_file8,
|
|
2933
|
+
L: 38,
|
|
2934
|
+
S: void 0,
|
|
2935
|
+
C: (f, a) => f(...a)
|
|
2936
|
+
});
|
|
2937
|
+
setValidationMessage(t("failed to recover identity message"));
|
|
2938
|
+
});
|
|
2939
|
+
} else {
|
|
2940
|
+
void client.halo.createIdentity({
|
|
2941
|
+
displayName: value
|
|
2942
|
+
}).then((identity) => {
|
|
2943
|
+
send?.({
|
|
2944
|
+
type: "selectIdentity",
|
|
2945
|
+
identity
|
|
2946
|
+
});
|
|
2947
|
+
}, (error) => {
|
|
2948
|
+
log8.catch(error, void 0, {
|
|
2949
|
+
F: __dxlog_file8,
|
|
2950
|
+
L: 48,
|
|
2951
|
+
S: void 0,
|
|
2952
|
+
C: (f, a) => f(...a)
|
|
2953
|
+
});
|
|
2954
|
+
setValidationMessage(t("failed to create identity message"));
|
|
2955
|
+
});
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
return /* @__PURE__ */ React33.createElement(IdentityInputImpl, {
|
|
2959
|
+
...props,
|
|
2960
|
+
onDisplayNameConfirm: createIdentity,
|
|
2961
|
+
validationMessage
|
|
2962
|
+
});
|
|
2963
|
+
};
|
|
2964
|
+
var IdentityInputImpl = (props) => {
|
|
2965
|
+
const { method, send, active, onDisplayNameConfirm, validationMessage } = props;
|
|
2966
|
+
const disabled = !active;
|
|
2967
|
+
const { t } = useTranslation18("os");
|
|
2968
|
+
const [inputValue, setInputValue] = useState10("");
|
|
2969
|
+
const isRecover = method === "recover identity";
|
|
2970
|
+
return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement("div", {
|
|
2971
|
+
role: "none",
|
|
2972
|
+
className: "grow flex flex-col justify-center"
|
|
2973
|
+
}, /* @__PURE__ */ React33.createElement(Input, {
|
|
2974
|
+
validationMessage,
|
|
2975
|
+
label: /* @__PURE__ */ React33.createElement(StepHeading, null, t(isRecover ? "recover identity input label" : "new identity input label")),
|
|
2976
|
+
disabled,
|
|
2977
|
+
"data-testid": "identity-input",
|
|
2978
|
+
placeholder: isRecover ? "Type your recovery phrase" : "Type a display name",
|
|
2979
|
+
onChange: ({ target: { value } }) => setInputValue(value)
|
|
2980
|
+
})), /* @__PURE__ */ React33.createElement(Actions, null, /* @__PURE__ */ React33.createElement(Action, {
|
|
2981
|
+
variant: "ghost",
|
|
2982
|
+
disabled,
|
|
2983
|
+
onClick: () => send?.({
|
|
2984
|
+
type: "deselectAuthMethod"
|
|
2985
|
+
}),
|
|
2986
|
+
"data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-back`
|
|
2987
|
+
}, t("back label")), /* @__PURE__ */ React33.createElement(Action, {
|
|
2988
|
+
variant: "primary",
|
|
2989
|
+
disabled,
|
|
2990
|
+
onClick: () => onDisplayNameConfirm?.(inputValue),
|
|
2991
|
+
"data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-continue`
|
|
2992
|
+
}, t("continue label"))));
|
|
2993
|
+
};
|
|
2994
|
+
|
|
2995
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAccepted.tsx
|
|
2996
|
+
import React34, { cloneElement as cloneElement3 } from "react";
|
|
2997
|
+
import { useTranslation as useTranslation19 } from "@dxos/react-ui";
|
|
2998
|
+
|
|
2999
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx
|
|
3000
|
+
import React35, { useState as useState11, useEffect as useEffect5, cloneElement as cloneElement4 } from "react";
|
|
3001
|
+
import { log as log9 } from "@dxos/log";
|
|
3002
|
+
import { useTranslation as useTranslation20 } from "@dxos/react-ui";
|
|
3003
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx";
|
|
3004
|
+
var invitationCodeFromUrl = (text) => {
|
|
3005
|
+
try {
|
|
3006
|
+
const searchParams = new URLSearchParams(text.substring(text.lastIndexOf("?")));
|
|
3007
|
+
const invitation = searchParams.get("spaceInvitationCode") ?? searchParams.get("deviceInvitationCode");
|
|
3008
|
+
return invitation ?? text;
|
|
3009
|
+
} catch (err) {
|
|
3010
|
+
log9.catch(err, void 0, {
|
|
3011
|
+
F: __dxlog_file9,
|
|
3012
|
+
L: 25,
|
|
3013
|
+
S: void 0,
|
|
3014
|
+
C: (f, a) => f(...a)
|
|
3015
|
+
});
|
|
3016
|
+
return text;
|
|
3017
|
+
}
|
|
3018
|
+
};
|
|
3019
|
+
var InvitationInput = (props) => {
|
|
3020
|
+
const { Kind, active, send, unredeemedCode, onExit, exitActionParent, onDone, doneActionParent, succeededKeys } = props;
|
|
3021
|
+
const disabled = !active;
|
|
3022
|
+
const { t } = useTranslation20("os");
|
|
3023
|
+
const [inputValue, setInputValue] = useState11(unredeemedCode ?? "");
|
|
3024
|
+
useEffect5(() => {
|
|
3025
|
+
unredeemedCode && setInputValue(unredeemedCode ?? "");
|
|
3026
|
+
}, [
|
|
3027
|
+
unredeemedCode
|
|
3028
|
+
]);
|
|
3029
|
+
const handleNext = () => {
|
|
3030
|
+
if (inputValue.trim().length === 0) {
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
send({
|
|
3034
|
+
type: `set${Kind}InvitationCode`,
|
|
3035
|
+
code: invitationCodeFromUrl(inputValue),
|
|
3036
|
+
...Kind === "Space" && {
|
|
3037
|
+
succeededKeys
|
|
3038
|
+
}
|
|
3039
|
+
});
|
|
3040
|
+
};
|
|
3041
|
+
const exitAction = /* @__PURE__ */ React35.createElement(Action, {
|
|
3042
|
+
variant: "ghost",
|
|
3043
|
+
disabled,
|
|
3044
|
+
...onExit ? {
|
|
3045
|
+
onClick: () => onExit()
|
|
3046
|
+
} : {
|
|
3047
|
+
onClick: () => onDone?.(null)
|
|
3048
|
+
},
|
|
3049
|
+
"data-testid": "join-exit"
|
|
3050
|
+
}, t("cancel label"));
|
|
3051
|
+
return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("div", {
|
|
3052
|
+
role: "none",
|
|
3053
|
+
className: "grow flex flex-col justify-center"
|
|
3054
|
+
}, /* @__PURE__ */ React35.createElement(Input, {
|
|
3055
|
+
label: /* @__PURE__ */ React35.createElement(StepHeading, null, t("invitation input label")),
|
|
3056
|
+
// TODO(burdon): Translation.
|
|
3057
|
+
placeholder: "Type an invitation code",
|
|
3058
|
+
disabled,
|
|
3059
|
+
value: inputValue,
|
|
3060
|
+
onChange: ({ target: { value } }) => setInputValue(value),
|
|
3061
|
+
"data-autofocus": `inputting${Kind}InvitationCode`,
|
|
3062
|
+
"data-testid": `${Kind.toLowerCase()}-invitation-input`,
|
|
3063
|
+
onKeyUp: ({ key }) => key === "Enter" && handleNext()
|
|
3064
|
+
})), /* @__PURE__ */ React35.createElement(Actions, null, Kind === "Halo" ? null : exitActionParent ? /* @__PURE__ */ cloneElement4(exitActionParent, {}, exitAction) : doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, exitAction) : exitAction, /* @__PURE__ */ React35.createElement(Action, {
|
|
3065
|
+
variant: "primary",
|
|
3066
|
+
disabled: disabled || inputValue.trim().length === 0,
|
|
3067
|
+
onClick: handleNext,
|
|
3068
|
+
"data-testid": `${Kind.toLowerCase()}-invitation-input-continue`
|
|
3069
|
+
}, t("continue label"))));
|
|
3070
|
+
};
|
|
3071
|
+
|
|
3072
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/InvitationRescuer.tsx
|
|
3073
|
+
import React36 from "react";
|
|
3074
|
+
import { useTranslation as useTranslation21 } from "@dxos/react-ui";
|
|
3075
|
+
import { descriptionText as descriptionText10 } from "@dxos/react-ui-theme";
|
|
3076
|
+
var InvitationActions = ({
|
|
3077
|
+
// `invitationState` does report correct state, but here we evaluate whether `failReason` is a better source of truth
|
|
3078
|
+
// for the UI in particular.
|
|
3079
|
+
invitationState,
|
|
3080
|
+
onInvitationCancel,
|
|
3081
|
+
active,
|
|
3082
|
+
send,
|
|
3083
|
+
Kind,
|
|
3084
|
+
failReason
|
|
3085
|
+
}) => {
|
|
3086
|
+
const { t } = useTranslation21("os");
|
|
3087
|
+
if (failReason) {
|
|
3088
|
+
return /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement(StepHeading, {
|
|
3089
|
+
className: descriptionText10
|
|
3090
|
+
}, t(failReason === "timeout" ? "timeout status label" : failReason === "cancelled" ? "cancelled status label" : "error status label")), /* @__PURE__ */ React36.createElement("div", {
|
|
3091
|
+
role: "none",
|
|
3092
|
+
className: "grow"
|
|
3093
|
+
}), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
|
|
3094
|
+
disabled: !active,
|
|
3095
|
+
onClick: () => send({
|
|
3096
|
+
type: `reset${Kind}Invitation`
|
|
3097
|
+
}),
|
|
3098
|
+
"data-testid": "invitation-rescuer-reset"
|
|
3099
|
+
}, t("reset label"))));
|
|
3100
|
+
} else {
|
|
3101
|
+
return /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement(StepHeading, {
|
|
3102
|
+
className: descriptionText10
|
|
3103
|
+
}, t("connecting status label")), /* @__PURE__ */ React36.createElement("div", {
|
|
3104
|
+
role: "none",
|
|
3105
|
+
className: "grow"
|
|
3106
|
+
}), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
|
|
3107
|
+
disabled: true,
|
|
3108
|
+
classNames: "order-2",
|
|
3109
|
+
"data-testid": "next"
|
|
3110
|
+
}, t("next label")), /* @__PURE__ */ React36.createElement(Action, {
|
|
3111
|
+
disabled: !active,
|
|
3112
|
+
onClick: onInvitationCancel,
|
|
3113
|
+
"data-testid": "invitation-rescuer-cancel"
|
|
3114
|
+
}, t("cancel label"))));
|
|
3115
|
+
}
|
|
3116
|
+
};
|
|
3117
|
+
var InvitationRescuer = (props) => {
|
|
3118
|
+
const { Kind, invitationState, active, send } = props;
|
|
3119
|
+
const { t } = useTranslation21("os");
|
|
3120
|
+
return /* @__PURE__ */ React36.createElement(React36.Fragment, null, typeof invitationState === "undefined" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("div", {
|
|
3121
|
+
role: "none",
|
|
3122
|
+
className: "grow flex flex-col justify-center"
|
|
3123
|
+
}, /* @__PURE__ */ React36.createElement(StepHeading, {
|
|
3124
|
+
className: descriptionText10
|
|
3125
|
+
}, "There was a problem joining the space")), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
|
|
3126
|
+
disabled: !active,
|
|
3127
|
+
"data-testid": "invitation-rescuer-blank-reset",
|
|
3128
|
+
onClick: () => send({
|
|
3129
|
+
type: `reset${Kind}Invitation`
|
|
3130
|
+
})
|
|
3131
|
+
}, t("reset label")))) : /* @__PURE__ */ React36.createElement(InvitationActions, props));
|
|
3132
|
+
};
|
|
3133
|
+
|
|
3134
|
+
// packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAuthenticator.tsx
|
|
3135
|
+
import React37, { useState as useState12 } from "react";
|
|
3136
|
+
import { Invitation as Invitation6 } from "@dxos/react-client/invitations";
|
|
3137
|
+
import { Input as Input3, useTranslation as useTranslation22 } from "@dxos/react-ui";
|
|
3138
|
+
import { descriptionText as descriptionText11 } from "@dxos/react-ui-theme";
|
|
3139
|
+
import { hexToEmoji as hexToEmoji5 } from "@dxos/util";
|
|
3140
|
+
var pinLength = 6;
|
|
3141
|
+
var InvitationAuthenticator = ({ failed, Kind, authMethod, active, pending, invitationId, onInvitationAuthenticate, onInvitationCancel }) => {
|
|
3142
|
+
const disabled = !active || pending;
|
|
3143
|
+
const { t } = useTranslation22("os");
|
|
3144
|
+
const invitationType = Kind.toLowerCase();
|
|
3145
|
+
const [authCode, setAuthCode] = useState12("");
|
|
3146
|
+
const onChange = ({ target: { value } }) => {
|
|
3147
|
+
setAuthCode(value);
|
|
3148
|
+
if (value.length === pinLength) {
|
|
3149
|
+
document.querySelector(`[data-autofocus-pinlength="${invitationType}"]`)?.focus();
|
|
3150
|
+
}
|
|
3151
|
+
};
|
|
3152
|
+
return /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement("div", {
|
|
3153
|
+
role: "none",
|
|
3154
|
+
className: "grow flex flex-col justify-center gap-4"
|
|
3155
|
+
}, /* @__PURE__ */ React37.createElement(Input3.Root, failed && {
|
|
3156
|
+
validationValence: "error"
|
|
3157
|
+
}, /* @__PURE__ */ React37.createElement(Input3.Label, {
|
|
3158
|
+
asChild: true
|
|
3159
|
+
}, authMethod === Invitation6.AuthMethod.SHARED_SECRET ? /* @__PURE__ */ React37.createElement(StepHeading, null, t("auth code input label")) : /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement(StepHeading, {
|
|
3160
|
+
className: descriptionText11
|
|
3161
|
+
}, t("authenticating label")), /* @__PURE__ */ React37.createElement("div", {
|
|
3162
|
+
role: "none",
|
|
3163
|
+
className: "grow"
|
|
3164
|
+
}))), authMethod === Invitation6.AuthMethod.SHARED_SECRET && /* @__PURE__ */ React37.createElement(Input3.PinInput, {
|
|
3165
|
+
disabled,
|
|
3166
|
+
length: pinLength,
|
|
3167
|
+
onChange,
|
|
3168
|
+
inputMode: "numeric",
|
|
3169
|
+
autoComplete: "off",
|
|
3170
|
+
pattern: "\\d*",
|
|
3171
|
+
"data-autofocus": `connecting${Kind}Invitation inputting${Kind}VerificationCode authenticationFailing${Kind}VerificationCode authenticating${Kind}VerificationCode`,
|
|
3172
|
+
"data-prevent-ios-autofocus": true,
|
|
3173
|
+
"data-testid": `${invitationType}-auth-code-input`,
|
|
3174
|
+
"data-1p-ignore": true
|
|
3175
|
+
}), failed && /* @__PURE__ */ React37.createElement(Input3.DescriptionAndValidation, {
|
|
3176
|
+
classNames: "text-center"
|
|
3177
|
+
}, /* @__PURE__ */ React37.createElement(Input3.Validation, null, t("failed to authenticate message")))), invitationId && authMethod === Invitation6.AuthMethod.SHARED_SECRET && /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement(Label, null, t("auth other device emoji message")), /* @__PURE__ */ React37.createElement("div", {
|
|
3178
|
+
className: "flex justify-center"
|
|
3179
|
+
}, /* @__PURE__ */ React37.createElement(Emoji, {
|
|
3180
|
+
text: hexToEmoji5(invitationId)
|
|
3181
|
+
})))), /* @__PURE__ */ React37.createElement(Actions, null, /* @__PURE__ */ React37.createElement(Action, {
|
|
3182
|
+
variant: "ghost",
|
|
3183
|
+
disabled,
|
|
3184
|
+
onClick: () => onInvitationCancel?.(),
|
|
3185
|
+
"data-testid": `${invitationType}-invitation-authenticator-cancel`
|
|
3186
|
+
}, t("cancel label")), /* @__PURE__ */ React37.createElement(Action, {
|
|
3187
|
+
variant: "primary",
|
|
3188
|
+
disabled,
|
|
3189
|
+
onClick: () => onInvitationAuthenticate?.(authCode),
|
|
3190
|
+
"data-autofocus-pinlength": invitationType,
|
|
3191
|
+
"data-testid": `${invitationType}-invitation-authenticator-next`
|
|
3192
|
+
}, t("next label"))));
|
|
3193
|
+
};
|
|
3194
|
+
|
|
3195
|
+
// packages/sdk/shell/src/styles/panelStyles.ts
|
|
3196
|
+
var stepStyles = "pbs-1 pbe-3 pli-3";
|
|
3197
|
+
|
|
3198
|
+
// packages/sdk/shell/src/styles/invitationStatusStyles.ts
|
|
3199
|
+
import { Invitation as Invitation7 } from "@dxos/react-client/invitations";
|
|
3200
|
+
var inactiveBgColor = "bg-neutral-100 dark:bg-neutral-600";
|
|
3201
|
+
var activeBgColor = "bg-primary-500 dark:bg-primary-400";
|
|
3202
|
+
var successBgColor = "bg-success-500 dark:bg-success-400";
|
|
3203
|
+
var errorBgColor = "bg-error-500 dark:bg-error-400";
|
|
3204
|
+
var cancelledBgColor = "bg-warning-500 dark:bg-warning-400";
|
|
3205
|
+
var inactiveTextColor = "text-neutral-100 dark:text-neutral-600";
|
|
3206
|
+
var activeTextColor = "text-primary-400 dark:text-primary-500";
|
|
3207
|
+
var successTextColor = "text-success-400 dark:text-success-500";
|
|
3208
|
+
var errorTextColor = "text-error-400 dark:text-error-500";
|
|
3209
|
+
var cancelledTextColor = "text-warning-400 dark:text-warning-500";
|
|
3210
|
+
var inactiveStrokeColor = "stroke-neutral-100 dark:stroke-neutral-700";
|
|
3211
|
+
var activeStrokeColor = "stroke-primary-400 dark:stroke-primary-150";
|
|
3212
|
+
var successStrokeColor = "stroke-success-300 dark:stroke-primary-400";
|
|
3213
|
+
var errorStrokeColor = "stroke-error-300 dark:stroke-error-500";
|
|
3214
|
+
var cancelledStrokeColor = "stroke-warning-300 dark:stroke-warning-500";
|
|
3215
|
+
var resolvedStrokeColor = (status) => status === Invitation7.State.ERROR ? errorStrokeColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledStrokeColor : successStrokeColor;
|
|
3216
|
+
var resolvedBgColor = (status) => status === Invitation7.State.ERROR ? errorBgColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledBgColor : successBgColor;
|
|
3217
|
+
var resolvedTextColor = (status) => status === Invitation7.State.ERROR ? errorTextColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledTextColor : successTextColor;
|
|
3218
|
+
|
|
3219
|
+
// packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
|
|
3220
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx";
|
|
3221
|
+
var JoinPanelImpl = (props) => {
|
|
3222
|
+
const {
|
|
3223
|
+
titleId,
|
|
3224
|
+
send,
|
|
3225
|
+
activeView,
|
|
3226
|
+
failed,
|
|
3227
|
+
mode,
|
|
3228
|
+
unredeemedCodes,
|
|
3229
|
+
invitationIds,
|
|
3230
|
+
invitationStates,
|
|
3231
|
+
invitationAuthMethods,
|
|
3232
|
+
succeededKeys,
|
|
3233
|
+
failReasons,
|
|
3234
|
+
onExit,
|
|
3235
|
+
onHaloDone,
|
|
3236
|
+
// onSpaceDone,
|
|
3237
|
+
exitActionParent,
|
|
3238
|
+
doneActionParent,
|
|
3239
|
+
onHaloInvitationCancel,
|
|
3240
|
+
onSpaceInvitationCancel,
|
|
3241
|
+
onHaloInvitationAuthenticate,
|
|
3242
|
+
onSpaceInvitationAuthenticate,
|
|
3243
|
+
onCancelResetStorage,
|
|
3244
|
+
onConfirmResetStorage,
|
|
3245
|
+
IdentityInput: IdentityInputComponent = IdentityInput,
|
|
3246
|
+
ConfirmReset: ConfirmResetComponent = ConfirmReset
|
|
3247
|
+
} = props;
|
|
3248
|
+
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, mode !== "halo-only" && /* @__PURE__ */ React38.createElement(JoinHeading, {
|
|
3249
|
+
titleId,
|
|
3250
|
+
mode,
|
|
3251
|
+
onExit,
|
|
3252
|
+
exitActionParent
|
|
3253
|
+
}), /* @__PURE__ */ React38.createElement(Viewport.Root, {
|
|
3254
|
+
focusManaged: true,
|
|
3255
|
+
activeView
|
|
3256
|
+
}, /* @__PURE__ */ React38.createElement(Viewport.Views, null, /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3257
|
+
classNames: stepStyles,
|
|
3258
|
+
id: "addition method chooser"
|
|
3259
|
+
}, /* @__PURE__ */ React38.createElement(AdditionMethodChooser, {
|
|
3260
|
+
send,
|
|
3261
|
+
active: activeView === "addition method chooser"
|
|
3262
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3263
|
+
classNames: stepStyles,
|
|
3264
|
+
id: "reset storage confirmation"
|
|
3265
|
+
}, /* @__PURE__ */ React38.createElement(ConfirmResetComponent, {
|
|
3266
|
+
send,
|
|
3267
|
+
active: activeView === "reset storage confirmation",
|
|
3268
|
+
onCancel: onCancelResetStorage,
|
|
3269
|
+
onConfirm: onConfirmResetStorage
|
|
3270
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3271
|
+
classNames: stepStyles,
|
|
3272
|
+
id: "create identity input"
|
|
3273
|
+
}, /* @__PURE__ */ React38.createElement(IdentityInputComponent, {
|
|
3274
|
+
send,
|
|
3275
|
+
method: "create identity",
|
|
3276
|
+
active: activeView === "create identity input"
|
|
3277
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3278
|
+
classNames: stepStyles,
|
|
3279
|
+
id: "recover identity input"
|
|
3280
|
+
}, /* @__PURE__ */ React38.createElement(IdentityInputComponent, {
|
|
3281
|
+
send,
|
|
3282
|
+
method: "recover identity",
|
|
3283
|
+
active: activeView === "recover identity input"
|
|
3284
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3285
|
+
classNames: stepStyles,
|
|
3286
|
+
id: "halo invitation input"
|
|
3287
|
+
}, /* @__PURE__ */ React38.createElement(InvitationInput, {
|
|
3288
|
+
send,
|
|
3289
|
+
Kind: "Halo",
|
|
3290
|
+
active: activeView === "halo invitation input",
|
|
3291
|
+
...unredeemedCodes?.Halo && {
|
|
3292
|
+
unredeemedCode: unredeemedCodes.Halo
|
|
3293
|
+
},
|
|
3294
|
+
...succeededKeys?.Halo && {
|
|
3295
|
+
succeededKeys: succeededKeys.Halo
|
|
3296
|
+
}
|
|
3297
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3298
|
+
classNames: stepStyles,
|
|
3299
|
+
id: "halo invitation rescuer"
|
|
3300
|
+
}, /* @__PURE__ */ React38.createElement(InvitationRescuer, {
|
|
3301
|
+
send,
|
|
3302
|
+
Kind: "Halo",
|
|
3303
|
+
active: activeView === "halo invitation rescuer",
|
|
3304
|
+
invitationState: invitationStates?.Halo,
|
|
3305
|
+
onInvitationCancel: onHaloInvitationCancel,
|
|
3306
|
+
failReason: failReasons?.Halo
|
|
3307
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3308
|
+
classNames: stepStyles,
|
|
3309
|
+
id: "halo invitation authenticator"
|
|
3310
|
+
}, /* @__PURE__ */ React38.createElement(InvitationAuthenticator, {
|
|
3311
|
+
send,
|
|
3312
|
+
Kind: "Halo",
|
|
3313
|
+
invitationId: invitationIds?.Halo,
|
|
3314
|
+
authMethod: invitationAuthMethods?.Halo,
|
|
3315
|
+
active: activeView === "halo invitation authenticator",
|
|
3316
|
+
onInvitationCancel: onHaloInvitationCancel,
|
|
3317
|
+
onInvitationAuthenticate: onHaloInvitationAuthenticate,
|
|
3318
|
+
...failed.has("Halo") && {
|
|
3319
|
+
failed: true
|
|
3320
|
+
}
|
|
3321
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3322
|
+
classNames: stepStyles,
|
|
3323
|
+
id: "identity added"
|
|
3324
|
+
}, /* @__PURE__ */ React38.createElement(IdentityAdded, {
|
|
3325
|
+
send,
|
|
3326
|
+
mode,
|
|
3327
|
+
active: activeView === "identity added",
|
|
3328
|
+
doneActionParent,
|
|
3329
|
+
onDone: onHaloDone
|
|
3330
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3331
|
+
classNames: stepStyles,
|
|
3332
|
+
id: "space invitation input"
|
|
3333
|
+
}, /* @__PURE__ */ React38.createElement(InvitationInput, {
|
|
3334
|
+
send,
|
|
3335
|
+
Kind: "Space",
|
|
3336
|
+
active: activeView === "space invitation input",
|
|
3337
|
+
...unredeemedCodes?.Space && {
|
|
3338
|
+
unredeemedCode: unredeemedCodes.Space
|
|
3339
|
+
},
|
|
3340
|
+
...succeededKeys?.Space && {
|
|
3341
|
+
succeededKeys: succeededKeys.Space
|
|
3342
|
+
},
|
|
3343
|
+
onExit,
|
|
3344
|
+
exitActionParent
|
|
3345
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3346
|
+
classNames: stepStyles,
|
|
3347
|
+
id: "space invitation rescuer"
|
|
3348
|
+
}, /* @__PURE__ */ React38.createElement(InvitationRescuer, {
|
|
3349
|
+
send,
|
|
3350
|
+
Kind: "Space",
|
|
3351
|
+
active: activeView === "space invitation rescuer",
|
|
3352
|
+
invitationState: invitationStates?.Space,
|
|
3353
|
+
onInvitationCancel: onSpaceInvitationCancel,
|
|
3354
|
+
failReason: failReasons?.Space
|
|
3355
|
+
})), /* @__PURE__ */ React38.createElement(Viewport.View, {
|
|
3356
|
+
classNames: stepStyles,
|
|
3357
|
+
id: "space invitation authenticator"
|
|
3358
|
+
}, /* @__PURE__ */ React38.createElement(InvitationAuthenticator, {
|
|
3359
|
+
send,
|
|
3360
|
+
Kind: "Space",
|
|
3361
|
+
invitationId: invitationIds?.Space,
|
|
3362
|
+
authMethod: invitationAuthMethods?.Space,
|
|
3363
|
+
active: activeView === "space invitation authenticator",
|
|
3364
|
+
onInvitationCancel: onSpaceInvitationCancel,
|
|
3365
|
+
onInvitationAuthenticate: onSpaceInvitationAuthenticate,
|
|
3366
|
+
...failed.has("Space") && {
|
|
3367
|
+
failed: true
|
|
3368
|
+
}
|
|
3369
|
+
})))));
|
|
3370
|
+
};
|
|
3371
|
+
var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialDisposition = "default", initialInvitationCode, exitActionParent, onExit, doneActionParent, onDone: propsOnDone, onCancelResetStorage }) => {
|
|
3372
|
+
const client = useClient8();
|
|
3373
|
+
const identity = useIdentity2();
|
|
3374
|
+
const { hasIosKeyboard } = useThemeContext5();
|
|
3375
|
+
const titleId = useId8("joinPanel__heading", propsTitleId);
|
|
3376
|
+
const [joinState, joinSend, joinService] = useJoinMachine(client, {
|
|
3377
|
+
context: {
|
|
3378
|
+
mode,
|
|
3379
|
+
initialDisposition,
|
|
3380
|
+
identity,
|
|
3381
|
+
...initialInvitationCode && {
|
|
3382
|
+
[mode === "halo-only" ? "halo" : "space"]: {
|
|
3383
|
+
unredeemedCode: initialInvitationCode
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
});
|
|
3388
|
+
useEffect6(() => {
|
|
3389
|
+
const subscription = joinService.subscribe((state) => {
|
|
3390
|
+
log10("[state]", state, {
|
|
3391
|
+
F: __dxlog_file10,
|
|
3392
|
+
L: 210,
|
|
3393
|
+
S: void 0,
|
|
3394
|
+
C: (f, a) => f(...a)
|
|
3395
|
+
});
|
|
3396
|
+
});
|
|
3397
|
+
return subscription.unsubscribe;
|
|
3398
|
+
}, [
|
|
3399
|
+
joinService
|
|
3400
|
+
]);
|
|
3401
|
+
useEffect6(() => {
|
|
3402
|
+
const stateStack = joinState.configuration[0].id.split(".");
|
|
3403
|
+
const innermostState = stateStack[stateStack.length - 1];
|
|
3404
|
+
const autoFocusValue = innermostState === "finishingJoining" ? "successSpaceInvitation" : innermostState;
|
|
3405
|
+
const $nextAutofocus = document.querySelector(`[data-autofocus~="${autoFocusValue}"]`);
|
|
3406
|
+
if ($nextAutofocus && !(hasIosKeyboard && $nextAutofocus.hasAttribute("data-prevent-ios-autofocus"))) {
|
|
3407
|
+
$nextAutofocus.focus();
|
|
3408
|
+
}
|
|
3409
|
+
}, [
|
|
3410
|
+
joinState.value,
|
|
3411
|
+
hasIosKeyboard
|
|
3412
|
+
]);
|
|
3413
|
+
const activeView = useMemo4(() => {
|
|
3414
|
+
switch (true) {
|
|
3415
|
+
case joinState.matches({
|
|
3416
|
+
choosingIdentity: "choosingAuthMethod"
|
|
3417
|
+
}):
|
|
3418
|
+
return "addition method chooser";
|
|
3419
|
+
case joinState.matches("resettingIdentity"):
|
|
3420
|
+
return "reset storage confirmation";
|
|
3421
|
+
case joinState.matches({
|
|
3422
|
+
choosingIdentity: "creatingIdentity"
|
|
3423
|
+
}):
|
|
3424
|
+
return "create identity input";
|
|
3425
|
+
case joinState.matches({
|
|
3426
|
+
choosingIdentity: "recoveringIdentity"
|
|
3427
|
+
}):
|
|
3428
|
+
return "recover identity input";
|
|
3429
|
+
case joinState.matches({
|
|
3430
|
+
choosingIdentity: {
|
|
3431
|
+
acceptingHaloInvitation: "inputtingHaloInvitationCode"
|
|
3432
|
+
}
|
|
3433
|
+
}):
|
|
3434
|
+
return "halo invitation input";
|
|
3435
|
+
case [
|
|
3436
|
+
{
|
|
3437
|
+
choosingIdentity: {
|
|
3438
|
+
acceptingHaloInvitation: {
|
|
3439
|
+
acceptingRedeemedHaloInvitation: "connectingHaloInvitation"
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
},
|
|
3443
|
+
{
|
|
3444
|
+
choosingIdentity: {
|
|
3445
|
+
acceptingHaloInvitation: {
|
|
3446
|
+
acceptingRedeemedHaloInvitation: "failingHaloInvitation"
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
].some(joinState.matches):
|
|
3451
|
+
return "halo invitation rescuer";
|
|
3452
|
+
case [
|
|
3453
|
+
{
|
|
3454
|
+
choosingIdentity: {
|
|
3455
|
+
acceptingHaloInvitation: {
|
|
3456
|
+
acceptingRedeemedHaloInvitation: "inputtingHaloVerificationCode"
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
},
|
|
3460
|
+
{
|
|
3461
|
+
choosingIdentity: {
|
|
3462
|
+
acceptingHaloInvitation: {
|
|
3463
|
+
acceptingRedeemedHaloInvitation: "authenticatingHaloVerificationCode"
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
},
|
|
3467
|
+
{
|
|
3468
|
+
choosingIdentity: {
|
|
3469
|
+
acceptingHaloInvitation: {
|
|
3470
|
+
acceptingRedeemedHaloInvitation: "authenticationFailingHaloVerificationCode"
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
].some(joinState.matches):
|
|
3475
|
+
return "halo invitation authenticator";
|
|
3476
|
+
case [
|
|
3477
|
+
{
|
|
3478
|
+
choosingIdentity: {
|
|
3479
|
+
acceptingHaloInvitation: {
|
|
3480
|
+
acceptingRedeemedHaloInvitation: "successHaloInvitation"
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
},
|
|
3484
|
+
"finishingJoiningHalo"
|
|
3485
|
+
].some(joinState.matches):
|
|
3486
|
+
return "halo invitation accepted";
|
|
3487
|
+
case joinState.matches({
|
|
3488
|
+
choosingIdentity: "confirmingAddedIdentity"
|
|
3489
|
+
}):
|
|
3490
|
+
return "identity added";
|
|
3491
|
+
case joinState.matches({
|
|
3492
|
+
acceptingSpaceInvitation: "inputtingSpaceInvitationCode"
|
|
3493
|
+
}):
|
|
3494
|
+
return "space invitation input";
|
|
3495
|
+
case [
|
|
3496
|
+
{
|
|
3497
|
+
acceptingSpaceInvitation: {
|
|
3498
|
+
acceptingRedeemedSpaceInvitation: "connectingSpaceInvitation"
|
|
3499
|
+
}
|
|
3500
|
+
},
|
|
3501
|
+
{
|
|
3502
|
+
acceptingSpaceInvitation: {
|
|
3503
|
+
acceptingRedeemedSpaceInvitation: "failingSpaceInvitation"
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
].some(joinState.matches):
|
|
3507
|
+
return "space invitation rescuer";
|
|
3508
|
+
case [
|
|
3509
|
+
{
|
|
3510
|
+
acceptingSpaceInvitation: {
|
|
3511
|
+
acceptingRedeemedSpaceInvitation: "inputtingSpaceVerificationCode"
|
|
3512
|
+
}
|
|
3513
|
+
},
|
|
3514
|
+
{
|
|
3515
|
+
acceptingSpaceInvitation: {
|
|
3516
|
+
acceptingRedeemedSpaceInvitation: "authenticatingSpaceVerificationCode"
|
|
3517
|
+
}
|
|
3518
|
+
},
|
|
3519
|
+
{
|
|
3520
|
+
acceptingSpaceInvitation: {
|
|
3521
|
+
acceptingRedeemedSpaceInvitation: "authenticationFailingSpaceVerificationCode"
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
].some(joinState.matches):
|
|
3525
|
+
return "space invitation authenticator";
|
|
3526
|
+
case joinState.matches("finishingJoiningSpace"):
|
|
3527
|
+
return "space invitation accepted";
|
|
3528
|
+
default:
|
|
3529
|
+
return "never";
|
|
3530
|
+
}
|
|
3531
|
+
}, [
|
|
3532
|
+
joinState
|
|
3533
|
+
]);
|
|
3534
|
+
useEffect6(() => {
|
|
3535
|
+
switch (activeView) {
|
|
3536
|
+
case "halo invitation accepted":
|
|
3537
|
+
onHaloDone();
|
|
3538
|
+
break;
|
|
3539
|
+
case "space invitation accepted":
|
|
3540
|
+
onSpaceDone();
|
|
3541
|
+
break;
|
|
3542
|
+
}
|
|
3543
|
+
}, [
|
|
3544
|
+
activeView
|
|
3545
|
+
]);
|
|
3546
|
+
const failed = useMemo4(() => {
|
|
3547
|
+
const result = /* @__PURE__ */ new Set();
|
|
3548
|
+
switch (true) {
|
|
3549
|
+
case joinState.matches({
|
|
3550
|
+
choosingIdentity: {
|
|
3551
|
+
acceptingHaloInvitation: {
|
|
3552
|
+
acceptingRedeemedHaloInvitation: "authenticationFailingHaloVerificationCode"
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
}):
|
|
3556
|
+
result.add("Halo");
|
|
3557
|
+
break;
|
|
3558
|
+
case joinState.matches({
|
|
3559
|
+
acceptingSpaceInvitation: {
|
|
3560
|
+
acceptingRedeemedSpaceInvitation: "authenticationFailingSpaceVerificationCode"
|
|
3561
|
+
}
|
|
3562
|
+
}):
|
|
3563
|
+
result.add("Space");
|
|
3564
|
+
break;
|
|
3565
|
+
}
|
|
3566
|
+
return result;
|
|
3567
|
+
}, [
|
|
3568
|
+
joinState
|
|
3569
|
+
]);
|
|
3570
|
+
const unredeemedCodes = useMemo4(() => ({
|
|
3571
|
+
Halo: joinState.context.halo.unredeemedCode,
|
|
3572
|
+
Space: joinState.context.space.unredeemedCode
|
|
3573
|
+
}), [
|
|
3574
|
+
joinState
|
|
3575
|
+
]);
|
|
3576
|
+
const spaces = useMulticastObservable(client.spaces);
|
|
3577
|
+
const succeededKeys = useMemo4(() => ({
|
|
3578
|
+
Space: spaces ? new Set(spaces.map(({ key }) => key.toHex())) : void 0
|
|
3579
|
+
}), [
|
|
3580
|
+
spaces
|
|
3581
|
+
]);
|
|
3582
|
+
const invitationStates = useMemo4(() => ({
|
|
3583
|
+
Halo: joinState.context.halo.invitationObservable?.get().state,
|
|
3584
|
+
Space: joinState.context.space.invitationObservable?.get().state
|
|
3585
|
+
}), [
|
|
3586
|
+
joinState
|
|
3587
|
+
]);
|
|
3588
|
+
const invitationAuthMethods = useMemo4(() => ({
|
|
3589
|
+
Halo: joinState.context.halo.invitationObservable?.get().authMethod,
|
|
3590
|
+
Space: joinState.context.space.invitationObservable?.get().authMethod
|
|
3591
|
+
}), [
|
|
3592
|
+
joinState
|
|
3593
|
+
]);
|
|
3594
|
+
const invitationIds = useMemo4(() => ({
|
|
3595
|
+
Halo: joinState.context.halo.invitationObservable?.get().invitationId,
|
|
3596
|
+
Space: joinState.context.space.invitationObservable?.get().invitationId
|
|
3597
|
+
}), [
|
|
3598
|
+
joinState
|
|
3599
|
+
]);
|
|
3600
|
+
const failReasons = useMemo4(() => ({
|
|
3601
|
+
Halo: joinState.context.halo.failReason,
|
|
3602
|
+
Space: joinState.context.space.failReason
|
|
3603
|
+
}), [
|
|
3604
|
+
joinState
|
|
3605
|
+
]);
|
|
3606
|
+
const onHaloDone = useCallback6(() => {
|
|
3607
|
+
propsOnDone?.({
|
|
3608
|
+
identityKey: joinState.context.halo.invitation?.identityKey ?? null,
|
|
3609
|
+
swarmKey: joinState.context.halo.invitation?.swarmKey ?? null,
|
|
3610
|
+
spaceKey: joinState.context.halo.invitation?.spaceKey ?? null,
|
|
3611
|
+
target: joinState.context.halo.invitation?.target ?? null
|
|
3612
|
+
});
|
|
3613
|
+
}, [
|
|
3614
|
+
joinState,
|
|
3615
|
+
propsOnDone
|
|
3616
|
+
]);
|
|
3617
|
+
const onSpaceDone = useCallback6(() => {
|
|
3618
|
+
propsOnDone?.({
|
|
3619
|
+
identityKey: joinState.context.space.invitation?.identityKey ?? null,
|
|
3620
|
+
swarmKey: joinState.context.space.invitation?.swarmKey ?? null,
|
|
3621
|
+
spaceKey: joinState.context.space.invitation?.spaceKey ?? null,
|
|
3622
|
+
target: joinState.context.space.invitation?.target ?? null
|
|
3623
|
+
});
|
|
3624
|
+
}, [
|
|
3625
|
+
joinState,
|
|
3626
|
+
propsOnDone
|
|
3627
|
+
]);
|
|
3628
|
+
const onConfirmResetStorage = useCallback6(() => client.reset().then(() => {
|
|
3629
|
+
joinSend({
|
|
3630
|
+
type: "resetIdentity"
|
|
3631
|
+
});
|
|
3632
|
+
}), [
|
|
3633
|
+
client,
|
|
3634
|
+
joinSend
|
|
3635
|
+
]);
|
|
3636
|
+
return /* @__PURE__ */ React38.createElement(JoinPanelImpl, {
|
|
3637
|
+
titleId,
|
|
3638
|
+
mode,
|
|
3639
|
+
send: joinSend,
|
|
3640
|
+
activeView,
|
|
3641
|
+
failed,
|
|
3642
|
+
failReasons,
|
|
3643
|
+
pending: [
|
|
3644
|
+
"connecting",
|
|
3645
|
+
"authenticating"
|
|
3646
|
+
].some((str) => joinState?.configuration[0].id.includes(str)),
|
|
3647
|
+
unredeemedCodes,
|
|
3648
|
+
invitationIds,
|
|
3649
|
+
invitationStates,
|
|
3650
|
+
invitationAuthMethods,
|
|
3651
|
+
succeededKeys,
|
|
3652
|
+
identity,
|
|
3653
|
+
onExit,
|
|
3654
|
+
exitActionParent,
|
|
3655
|
+
doneActionParent,
|
|
3656
|
+
onHaloDone,
|
|
3657
|
+
onSpaceDone,
|
|
3658
|
+
onHaloInvitationCancel: () => joinState.context.halo.invitationObservable?.cancel(),
|
|
3659
|
+
onSpaceInvitationCancel: () => joinState.context.space.invitationObservable?.cancel(),
|
|
3660
|
+
onHaloInvitationAuthenticate: (authCode) => {
|
|
3661
|
+
joinSend({
|
|
3662
|
+
type: "authenticateHaloVerificationCode"
|
|
3663
|
+
});
|
|
3664
|
+
return joinState.context.halo.invitationObservable?.authenticate(authCode);
|
|
3665
|
+
},
|
|
3666
|
+
onSpaceInvitationAuthenticate: (authCode) => {
|
|
3667
|
+
joinSend({
|
|
3668
|
+
type: "authenticateSpaceVerificationCode"
|
|
3669
|
+
});
|
|
3670
|
+
return joinState.context.space.invitationObservable?.authenticate(authCode);
|
|
3671
|
+
},
|
|
3672
|
+
onConfirmResetStorage,
|
|
3673
|
+
onCancelResetStorage
|
|
3674
|
+
});
|
|
3675
|
+
};
|
|
3676
|
+
|
|
3677
|
+
// packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
|
|
3678
|
+
import { Planet } from "@phosphor-icons/react";
|
|
3679
|
+
import React40, { useEffect as useEffect7, useMemo as useMemo5 } from "react";
|
|
3680
|
+
import { log as log13 } from "@dxos/log";
|
|
3681
|
+
import { useInvitationStatus as useInvitationStatus3 } from "@dxos/react-client/invitations";
|
|
3682
|
+
import { useId as useId9, useTranslation as useTranslation24 } from "@dxos/react-ui";
|
|
3683
|
+
|
|
3684
|
+
// packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts
|
|
3685
|
+
import { useMachine as useMachine3 } from "@xstate/react";
|
|
3686
|
+
import { assign as assign3, createMachine as createMachine3 } from "xstate";
|
|
3687
|
+
import { log as log11 } from "@dxos/log";
|
|
3688
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts";
|
|
3689
|
+
var spaceMachine = createMachine3({
|
|
3690
|
+
id: "space",
|
|
3691
|
+
predictableActionArguments: true,
|
|
3692
|
+
context: {
|
|
3693
|
+
space: null
|
|
3694
|
+
},
|
|
3695
|
+
initial: "managingSpace",
|
|
3696
|
+
states: {
|
|
3697
|
+
managingSpace: {},
|
|
3698
|
+
managingSpaceInvitation: {}
|
|
3699
|
+
},
|
|
3700
|
+
on: {
|
|
3701
|
+
deselectInvitation: {
|
|
3702
|
+
target: ".managingSpace",
|
|
3703
|
+
actions: [
|
|
3704
|
+
"unsetInvitation",
|
|
3705
|
+
"log"
|
|
3706
|
+
]
|
|
3707
|
+
},
|
|
3708
|
+
selectInvitation: {
|
|
3709
|
+
target: ".managingSpaceInvitation",
|
|
3710
|
+
actions: [
|
|
3711
|
+
"setInvitation",
|
|
3712
|
+
"log"
|
|
3713
|
+
]
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
}, {
|
|
3717
|
+
actions: {
|
|
3718
|
+
setInvitation: assign3({
|
|
3719
|
+
invitation: (context, event) => event?.invitation ?? null
|
|
3720
|
+
}),
|
|
3721
|
+
unsetInvitation: assign3({
|
|
3722
|
+
invitation: () => void 0
|
|
3723
|
+
}),
|
|
3724
|
+
log: (context, event) => {
|
|
3725
|
+
log11("[transition]", {
|
|
3726
|
+
event,
|
|
3727
|
+
context
|
|
3728
|
+
}, {
|
|
3729
|
+
F: __dxlog_file11,
|
|
3730
|
+
L: 53,
|
|
3731
|
+
S: void 0,
|
|
3732
|
+
C: (f, a) => f(...a)
|
|
3733
|
+
});
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
});
|
|
3737
|
+
var useSpaceMachine = (options) => {
|
|
3738
|
+
return useMachine3(spaceMachine, {
|
|
3739
|
+
...options,
|
|
3740
|
+
context: {
|
|
3741
|
+
...options?.context
|
|
3742
|
+
}
|
|
3743
|
+
});
|
|
3744
|
+
};
|
|
3745
|
+
|
|
3746
|
+
// packages/sdk/shell/src/panels/SpacePanel/steps/SpaceManager.tsx
|
|
3747
|
+
import { Placeholder as Placeholder2, UserPlus, UsersThree } from "@phosphor-icons/react";
|
|
3748
|
+
import React39, { useCallback as useCallback7, useState as useState13 } from "react";
|
|
3749
|
+
import { log as log12 } from "@dxos/log";
|
|
3750
|
+
import { useConfig } from "@dxos/react-client";
|
|
3751
|
+
import { useSpaceInvitations as useSpaceInvitations2 } from "@dxos/react-client/echo";
|
|
3752
|
+
import { Invitation as Invitation8, InvitationEncoder as InvitationEncoder4 } from "@dxos/react-client/invitations";
|
|
3753
|
+
import { ScrollArea, useTranslation as useTranslation23 } from "@dxos/react-ui";
|
|
3754
|
+
import { descriptionText as descriptionText12, mx as mx24 } from "@dxos/react-ui-theme";
|
|
3755
|
+
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/steps/SpaceManager.tsx";
|
|
3756
|
+
var activeActionKey = "dxos:react-shell/space-manager/active-action";
|
|
3757
|
+
var handleInvitationEvent = (invitation, subscription) => {
|
|
3758
|
+
const invitationCode = InvitationEncoder4.encode(invitation);
|
|
3759
|
+
if (invitation.state === Invitation8.State.CONNECTING) {
|
|
3760
|
+
log12.info(JSON.stringify({
|
|
3761
|
+
invitationCode,
|
|
3762
|
+
authCode: invitation.authCode
|
|
3763
|
+
}), void 0, {
|
|
3764
|
+
F: __dxlog_file12,
|
|
3765
|
+
L: 40,
|
|
3766
|
+
S: void 0,
|
|
3767
|
+
C: (f, a) => f(...a)
|
|
3768
|
+
});
|
|
3769
|
+
subscription.unsubscribe();
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
var SpaceManager = (props) => {
|
|
3773
|
+
const { space, target } = props;
|
|
3774
|
+
const { t } = useTranslation23("os");
|
|
3775
|
+
const config = useConfig();
|
|
3776
|
+
const invitations = useSpaceInvitations2(space?.key);
|
|
3777
|
+
const inviteActions = {
|
|
3778
|
+
inviteOne: {
|
|
3779
|
+
label: t("invite one label"),
|
|
3780
|
+
description: t("invite one description"),
|
|
3781
|
+
icon: UserPlus,
|
|
3782
|
+
onClick: useCallback7(() => {
|
|
3783
|
+
const invitation = space.share?.({
|
|
3784
|
+
type: Invitation8.Type.INTERACTIVE,
|
|
3785
|
+
authMethod: Invitation8.AuthMethod.SHARED_SECRET,
|
|
3786
|
+
multiUse: false,
|
|
3787
|
+
target
|
|
3788
|
+
});
|
|
3789
|
+
if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== "production") {
|
|
3790
|
+
const subscription = invitation.subscribe((invitation2) => handleInvitationEvent(invitation2, subscription));
|
|
3791
|
+
}
|
|
3792
|
+
}, [
|
|
3793
|
+
space
|
|
3794
|
+
])
|
|
3795
|
+
},
|
|
3796
|
+
inviteMany: {
|
|
3797
|
+
label: t("invite many label"),
|
|
3798
|
+
description: t("invite many description"),
|
|
3799
|
+
icon: UsersThree,
|
|
3800
|
+
onClick: useCallback7(() => {
|
|
3801
|
+
const invitation = space.share?.({
|
|
3802
|
+
type: Invitation8.Type.DELEGATED,
|
|
3803
|
+
authMethod: Invitation8.AuthMethod.KNOWN_PUBLIC_KEY,
|
|
3804
|
+
multiUse: true,
|
|
3805
|
+
target
|
|
3806
|
+
});
|
|
3807
|
+
if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== "production") {
|
|
3808
|
+
const subscription = invitation.subscribe((invitation2) => handleInvitationEvent(invitation2, subscription));
|
|
3809
|
+
}
|
|
3810
|
+
}, [
|
|
3811
|
+
space
|
|
3812
|
+
])
|
|
3813
|
+
}
|
|
3814
|
+
};
|
|
3815
|
+
return /* @__PURE__ */ React39.createElement(SpaceManagerImpl, {
|
|
3816
|
+
...props,
|
|
3817
|
+
invitations,
|
|
3818
|
+
inviteActions
|
|
3819
|
+
});
|
|
3820
|
+
};
|
|
3821
|
+
var headingFragment = "pis-3 pie-1 plb-1 mbe-1 font-medium";
|
|
3822
|
+
var SpaceManagerImpl = (props) => {
|
|
3823
|
+
const { active, space, createInvitationUrl, send, inviteActions: propsInviteActions, invitations, showInactiveInvitations, SpaceMemberList: SpaceMemberListComponent = SpaceMemberList, InvitationList: InvitationListComponent = InvitationList } = props;
|
|
3824
|
+
const { t } = useTranslation23("os");
|
|
3825
|
+
const inviteActions = propsInviteActions ?? {
|
|
3826
|
+
noopInvite: {
|
|
3827
|
+
label: t("create space invitation label"),
|
|
3828
|
+
description: "",
|
|
3829
|
+
icon: Placeholder2,
|
|
3830
|
+
onClick: () => {
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
};
|
|
3834
|
+
const [activeAction, setInternalActiveAction] = useState13(localStorage.getItem(activeActionKey) ?? "inviteOne");
|
|
3835
|
+
const setActiveAction = (nextAction) => {
|
|
3836
|
+
setInternalActiveAction(nextAction);
|
|
3837
|
+
localStorage.setItem(activeActionKey, nextAction);
|
|
3838
|
+
};
|
|
3839
|
+
const visibleInvitations = showInactiveInvitations ? invitations : invitations?.filter((invitation) => ![
|
|
3840
|
+
Invitation8.State.CANCELLED
|
|
3841
|
+
].includes(invitation.get().state));
|
|
3842
|
+
return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(ScrollArea.Root, {
|
|
3843
|
+
classNames: "grow shrink basis-28 -mli-2"
|
|
3844
|
+
}, /* @__PURE__ */ React39.createElement(ScrollArea.Viewport, {
|
|
3845
|
+
classNames: "is-full pie-2"
|
|
3846
|
+
}, !!visibleInvitations?.length && /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement("h3", {
|
|
3847
|
+
className: mx24(headingFragment, descriptionText12)
|
|
3848
|
+
}, t("invitation list heading")), /* @__PURE__ */ React39.createElement(InvitationListComponent, {
|
|
3849
|
+
className: "mb-2",
|
|
3850
|
+
send,
|
|
3851
|
+
invitations: visibleInvitations ?? [],
|
|
3852
|
+
onClickRemove: (invitation) => invitation.cancel(),
|
|
3853
|
+
createInvitationUrl
|
|
3854
|
+
}), /* @__PURE__ */ React39.createElement("h3", {
|
|
3855
|
+
className: mx24(headingFragment, descriptionText12, "mbs-2")
|
|
3856
|
+
}, t("space member list heading"))), /* @__PURE__ */ React39.createElement(SpaceMemberListComponent, {
|
|
3857
|
+
spaceKey: space.key,
|
|
3858
|
+
includeSelf: true
|
|
3859
|
+
})), /* @__PURE__ */ React39.createElement(ScrollArea.Scrollbar, {
|
|
3860
|
+
orientation: "vertical"
|
|
3861
|
+
}, /* @__PURE__ */ React39.createElement(ScrollArea.Thumb, null))), /* @__PURE__ */ React39.createElement(Actions, null, /* @__PURE__ */ React39.createElement(BifurcatedAction, {
|
|
3862
|
+
disabled: !active,
|
|
3863
|
+
actions: inviteActions,
|
|
3864
|
+
activeAction,
|
|
3865
|
+
onChangeActiveAction: setActiveAction,
|
|
3866
|
+
"data-testid": "spaces-panel.create-invitation"
|
|
3867
|
+
})));
|
|
3868
|
+
};
|
|
3869
|
+
|
|
3870
|
+
// packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
|
|
3871
|
+
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx";
|
|
3872
|
+
var SpacePanelHeading = ({ titleId, space, onDone }) => {
|
|
3873
|
+
const { t } = useTranslation24("os");
|
|
3874
|
+
const name = space.properties.name;
|
|
3875
|
+
return /* @__PURE__ */ React40.createElement(Heading, {
|
|
3876
|
+
titleId,
|
|
3877
|
+
title: t("space panel heading"),
|
|
3878
|
+
corner: /* @__PURE__ */ React40.createElement(CloseButton, {
|
|
3879
|
+
"data-testid": "identity-panel-done",
|
|
3880
|
+
onDone
|
|
3881
|
+
})
|
|
3882
|
+
}, /* @__PURE__ */ React40.createElement("div", {
|
|
3883
|
+
role: "none",
|
|
3884
|
+
className: "flex gap-4 items-center justify-center mlb-4"
|
|
3885
|
+
}, /* @__PURE__ */ React40.createElement(Planet, {
|
|
3886
|
+
size: 32,
|
|
3887
|
+
weight: "light"
|
|
3888
|
+
}), /* @__PURE__ */ React40.createElement("div", {
|
|
3889
|
+
className: "block text-start font-light text-xl"
|
|
3890
|
+
}, name ?? space.key.truncate())));
|
|
3891
|
+
};
|
|
3892
|
+
var SpacePanelImpl = (props) => {
|
|
3893
|
+
const { titleId, activeView, space, target, SpaceManager: SpaceManagerComponent = SpaceManager, InvitationManager: InvitationManagerComponent = InvitationManager, ...rest } = props;
|
|
3894
|
+
return /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement(SpacePanelHeading, {
|
|
3895
|
+
...rest,
|
|
3896
|
+
titleId,
|
|
3897
|
+
space
|
|
3898
|
+
}), /* @__PURE__ */ React40.createElement(Viewport.Root, {
|
|
3899
|
+
activeView
|
|
3900
|
+
}, /* @__PURE__ */ React40.createElement(Viewport.Views, null, /* @__PURE__ */ React40.createElement(Viewport.View, {
|
|
3901
|
+
id: "space manager",
|
|
3902
|
+
classNames: stepStyles
|
|
3903
|
+
}, /* @__PURE__ */ React40.createElement(SpaceManagerComponent, {
|
|
3904
|
+
active: activeView === "space manager",
|
|
3905
|
+
space,
|
|
3906
|
+
target,
|
|
3907
|
+
...rest
|
|
3908
|
+
})), /* @__PURE__ */ React40.createElement(Viewport.View, {
|
|
3909
|
+
id: "space invitation manager",
|
|
3910
|
+
classNames: stepStyles
|
|
3911
|
+
}, /* @__PURE__ */ React40.createElement(InvitationManagerComponent, {
|
|
3912
|
+
active: activeView === "space invitation manager",
|
|
3913
|
+
...rest,
|
|
3914
|
+
invitationUrl: props.invitationUrl
|
|
3915
|
+
})))));
|
|
3916
|
+
};
|
|
3917
|
+
var SpacePanelWithInvitationImpl = ({ invitation, ...props }) => {
|
|
3918
|
+
const invitationStatus = useInvitationStatus3(invitation);
|
|
3919
|
+
return /* @__PURE__ */ React40.createElement(SpacePanelImpl, {
|
|
3920
|
+
...props,
|
|
3921
|
+
...invitationStatus,
|
|
3922
|
+
invitationUrl: props.createInvitationUrl(invitationStatus.invitationCode)
|
|
3923
|
+
});
|
|
3924
|
+
};
|
|
3925
|
+
var SpacePanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code, ...props }) => {
|
|
3926
|
+
const titleId = useId9("spacePanel__heading", propsTitleId);
|
|
3927
|
+
const [spaceState, spaceSend, spaceService] = useSpaceMachine({
|
|
3928
|
+
context: {
|
|
3929
|
+
space: props.space
|
|
3930
|
+
}
|
|
3931
|
+
});
|
|
3932
|
+
useEffect7(() => {
|
|
3933
|
+
const subscription = spaceService.subscribe((state) => {
|
|
3934
|
+
log13("[state]", state, {
|
|
3935
|
+
F: __dxlog_file13,
|
|
3936
|
+
L: 94,
|
|
3937
|
+
S: void 0,
|
|
3938
|
+
C: (f, a) => f(...a)
|
|
3939
|
+
});
|
|
3940
|
+
});
|
|
3941
|
+
return subscription.unsubscribe;
|
|
3942
|
+
}, [
|
|
3943
|
+
spaceService
|
|
3944
|
+
]);
|
|
3945
|
+
const activeView = useMemo5(() => {
|
|
3946
|
+
switch (true) {
|
|
3947
|
+
case spaceState.matches("managingSpace"):
|
|
3948
|
+
return "space manager";
|
|
3949
|
+
case spaceState.matches("managingSpaceInvitation"):
|
|
3950
|
+
return "space invitation manager";
|
|
3951
|
+
default:
|
|
3952
|
+
return "never";
|
|
3953
|
+
}
|
|
3954
|
+
}, [
|
|
3955
|
+
spaceState
|
|
3956
|
+
]);
|
|
3957
|
+
const implProps = {
|
|
3958
|
+
...props,
|
|
3959
|
+
activeView,
|
|
3960
|
+
send: spaceSend,
|
|
3961
|
+
titleId,
|
|
3962
|
+
createInvitationUrl
|
|
3963
|
+
};
|
|
3964
|
+
return spaceState.context.invitation ? (
|
|
3965
|
+
// TODO(wittjosiah): Unused? Remove?
|
|
3966
|
+
/* @__PURE__ */ React40.createElement(SpacePanelWithInvitationImpl, {
|
|
3967
|
+
...implProps,
|
|
3968
|
+
invitation: spaceState.context.invitation
|
|
3969
|
+
})
|
|
3970
|
+
) : /* @__PURE__ */ React40.createElement(SpacePanelImpl, implProps);
|
|
3971
|
+
};
|
|
3972
|
+
|
|
3973
|
+
// packages/sdk/shell/src/panels/StatusPanel/StatusPanel.tsx
|
|
3974
|
+
import React41 from "react";
|
|
3975
|
+
import { Status, useTranslation as useTranslation25 } from "@dxos/react-ui";
|
|
3976
|
+
var StatusPanel = ({ titleId }) => {
|
|
3977
|
+
const { t } = useTranslation25("os");
|
|
3978
|
+
return /* @__PURE__ */ React41.createElement("div", {
|
|
3979
|
+
className: "grid place-items-center p-2 gap-2"
|
|
3980
|
+
}, /* @__PURE__ */ React41.createElement("p", {
|
|
3981
|
+
id: titleId,
|
|
3982
|
+
className: "font-medium text-center"
|
|
3983
|
+
}, t("resetting message")), /* @__PURE__ */ React41.createElement(Status, {
|
|
3984
|
+
indeterminate: true
|
|
3985
|
+
}, t("resetting message")));
|
|
3986
|
+
};
|
|
3987
|
+
|
|
3988
|
+
// packages/sdk/shell/src/composites/IdentityDialog/IdentityDialog.tsx
|
|
3989
|
+
var IdentityDialog = (props) => {
|
|
3990
|
+
const titleId = useId10("identityDialog__title", props.title);
|
|
3991
|
+
return /* @__PURE__ */ React42.createElement(Dialog.Root, {
|
|
3992
|
+
defaultOpen: true,
|
|
3993
|
+
onOpenChange: (open) => open || props.onDone?.()
|
|
3994
|
+
}, /* @__PURE__ */ React42.createElement(Dialog.Portal, null, /* @__PURE__ */ React42.createElement(Dialog.Overlay, null, /* @__PURE__ */ React42.createElement(Dialog.Content, {
|
|
3995
|
+
"aria-labelledby": titleId,
|
|
3996
|
+
onOpenAutoFocus: (e) => e.preventDefault()
|
|
3997
|
+
}, /* @__PURE__ */ React42.createElement(ClipboardProvider, null, /* @__PURE__ */ React42.createElement(IdentityPanel, {
|
|
3998
|
+
...props,
|
|
3999
|
+
titleId,
|
|
4000
|
+
doneActionParent: /* @__PURE__ */ React42.createElement(Dialog.Close, {
|
|
4001
|
+
asChild: true
|
|
4002
|
+
})
|
|
4003
|
+
}))))));
|
|
4004
|
+
};
|
|
4005
|
+
|
|
4006
|
+
// packages/sdk/shell/src/composites/JoinDialog/JoinDialog.tsx
|
|
4007
|
+
import React43 from "react";
|
|
4008
|
+
import { AlertDialog, useId as useId11, useVisualViewport } from "@dxos/react-ui";
|
|
4009
|
+
var JoinDialog = (joinPanelProps) => {
|
|
4010
|
+
const titleId = useId11("joinDialog__title");
|
|
4011
|
+
const { height } = useVisualViewport();
|
|
4012
|
+
return /* @__PURE__ */ React43.createElement(AlertDialog.Root, {
|
|
4013
|
+
defaultOpen: true,
|
|
4014
|
+
onOpenChange: (open) => open || (joinPanelProps.onExit ? joinPanelProps.onExit() : joinPanelProps.onDone?.(null))
|
|
4015
|
+
}, /* @__PURE__ */ React43.createElement(AlertDialog.Portal, null, /* @__PURE__ */ React43.createElement(AlertDialog.Overlay, {
|
|
4016
|
+
classNames: "backdrop-blur",
|
|
4017
|
+
...height && {
|
|
4018
|
+
style: {
|
|
4019
|
+
blockSize: `${height}px`
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
}, /* @__PURE__ */ React43.createElement(AlertDialog.Content, {
|
|
4023
|
+
"aria-labelledby": titleId
|
|
4024
|
+
}, /* @__PURE__ */ React43.createElement(JoinPanel, {
|
|
4025
|
+
...joinPanelProps,
|
|
4026
|
+
titleId,
|
|
4027
|
+
exitActionParent: /* @__PURE__ */ React43.createElement(AlertDialog.Cancel, {
|
|
4028
|
+
asChild: true
|
|
4029
|
+
}),
|
|
4030
|
+
doneActionParent: /* @__PURE__ */ React43.createElement(AlertDialog.Action, {
|
|
4031
|
+
asChild: true
|
|
4032
|
+
})
|
|
4033
|
+
})))));
|
|
4034
|
+
};
|
|
4035
|
+
|
|
4036
|
+
// packages/sdk/shell/src/composites/Shell/run-shell.tsx
|
|
4037
|
+
import React47, { StrictMode } from "react";
|
|
4038
|
+
import { createRoot } from "react-dom/client";
|
|
4039
|
+
import { DEFAULT_CLIENT_CHANNEL, DEFAULT_SHELL_CHANNEL } from "@dxos/client-protocol";
|
|
4040
|
+
import { AgentHostingProvider, ClientProvider, ClientServicesProxy, Config, ShellDisplay as ShellDisplay2 } from "@dxos/react-client";
|
|
4041
|
+
import { Button as Button11, Dialog as Dialog3, ThemeProvider, Tooltip as Tooltip8, useTranslation as useTranslation26 } from "@dxos/react-ui";
|
|
4042
|
+
import { defaultTx } from "@dxos/react-ui-theme";
|
|
4043
|
+
import { createIFramePort } from "@dxos/rpc-tunnel";
|
|
4044
|
+
|
|
4045
|
+
// packages/sdk/shell/src/composites/Shell/Shell.tsx
|
|
4046
|
+
import React46, { useEffect as useEffect8, useState as useState14 } from "react";
|
|
4047
|
+
import { log as log14 } from "@dxos/log";
|
|
4048
|
+
import { useClient as useClient9 } from "@dxos/react-client";
|
|
4049
|
+
import { ShellDisplay, ShellLayout } from "@dxos/react-client";
|
|
4050
|
+
import { useSpace as useSpace2 } from "@dxos/react-client/echo";
|
|
4051
|
+
|
|
4052
|
+
// packages/sdk/shell/src/composites/SpaceDialog/SpaceDialog.tsx
|
|
4053
|
+
import React44 from "react";
|
|
4054
|
+
import { Dialog as Dialog2, useId as useId12 } from "@dxos/react-ui";
|
|
4055
|
+
var SpaceDialog = (spacePanelProps) => {
|
|
4056
|
+
const titleId = useId12("spaceDialog__title");
|
|
4057
|
+
return /* @__PURE__ */ React44.createElement(Dialog2.Root, {
|
|
4058
|
+
defaultOpen: true,
|
|
4059
|
+
onOpenChange: (open) => open || spacePanelProps.onDone?.()
|
|
4060
|
+
}, /* @__PURE__ */ React44.createElement(Dialog2.Portal, null, /* @__PURE__ */ React44.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React44.createElement(Dialog2.Content, {
|
|
4061
|
+
"aria-labelledby": titleId
|
|
4062
|
+
}, /* @__PURE__ */ React44.createElement(ClipboardProvider, null, /* @__PURE__ */ React44.createElement(SpacePanel, {
|
|
4063
|
+
...spacePanelProps,
|
|
4064
|
+
titleId,
|
|
4065
|
+
doneActionParent: /* @__PURE__ */ React44.createElement(Dialog2.Close, {
|
|
4066
|
+
asChild: true
|
|
4067
|
+
})
|
|
4068
|
+
}))))));
|
|
4069
|
+
};
|
|
4070
|
+
|
|
4071
|
+
// packages/sdk/shell/src/composites/StatusDialog/StatusDialog.tsx
|
|
4072
|
+
import React45 from "react";
|
|
4073
|
+
import { AlertDialog as AlertDialog2, useId as useId13 } from "@dxos/react-ui";
|
|
4074
|
+
var StatusDialog = () => {
|
|
4075
|
+
const titleId = useId13("statusDialog__title");
|
|
4076
|
+
return /* @__PURE__ */ React45.createElement(AlertDialog2.Root, {
|
|
4077
|
+
open: true
|
|
4078
|
+
}, /* @__PURE__ */ React45.createElement(AlertDialog2.Portal, null, /* @__PURE__ */ React45.createElement(AlertDialog2.Overlay, null, /* @__PURE__ */ React45.createElement(AlertDialog2.Content, {
|
|
4079
|
+
"aria-labelledby": titleId
|
|
4080
|
+
}, /* @__PURE__ */ React45.createElement(StatusPanel, {
|
|
4081
|
+
titleId
|
|
4082
|
+
})))));
|
|
4083
|
+
};
|
|
4084
|
+
|
|
4085
|
+
// packages/sdk/shell/src/composites/Shell/Shell.tsx
|
|
4086
|
+
var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/composites/Shell/Shell.tsx";
|
|
4087
|
+
var blurActiveElement = () => document.activeElement?.blur?.();
|
|
4088
|
+
var Shell = ({ runtime }) => {
|
|
4089
|
+
const [{ layout, invitationCode, spaceKey, spaceId, target }, setLayout] = useState14({
|
|
4090
|
+
layout: runtime.layout,
|
|
4091
|
+
invitationCode: runtime.invitationCode,
|
|
4092
|
+
spaceKey: runtime.spaceKey,
|
|
4093
|
+
spaceId: runtime.spaceId,
|
|
4094
|
+
target: runtime.target
|
|
4095
|
+
});
|
|
4096
|
+
const [{ invitationUrl, deviceInvitationParam, spaceInvitationParam }, setInvitationUrl] = useState14({
|
|
4097
|
+
invitationUrl: runtime.invitationUrl,
|
|
4098
|
+
deviceInvitationParam: runtime.deviceInvitationParam,
|
|
4099
|
+
spaceInvitationParam: runtime.spaceInvitationParam
|
|
4100
|
+
});
|
|
4101
|
+
const client = useClient9();
|
|
4102
|
+
const space = useSpace2(spaceId ?? spaceKey);
|
|
4103
|
+
const createDeviceInvitationUrl = (invitationCode2) => {
|
|
4104
|
+
const baseUrl = new URL(invitationUrl);
|
|
4105
|
+
baseUrl.searchParams.set(deviceInvitationParam, invitationCode2);
|
|
4106
|
+
return baseUrl.toString();
|
|
4107
|
+
};
|
|
4108
|
+
const createSpaceInvitationUrl = (invitationCode2) => {
|
|
4109
|
+
const baseUrl = new URL(invitationUrl);
|
|
4110
|
+
baseUrl.searchParams.set(spaceInvitationParam, invitationCode2);
|
|
4111
|
+
return baseUrl.toString();
|
|
4112
|
+
};
|
|
4113
|
+
useEffect8(() => {
|
|
4114
|
+
const unsubscribeLayout = runtime.layoutUpdate.on((request) => setLayout(request));
|
|
4115
|
+
const unsubscribeInvitationUrl = runtime.invitationUrlUpdate.on((request) => setInvitationUrl(request));
|
|
4116
|
+
return () => {
|
|
4117
|
+
unsubscribeLayout();
|
|
4118
|
+
unsubscribeInvitationUrl();
|
|
4119
|
+
};
|
|
4120
|
+
}, [
|
|
4121
|
+
runtime
|
|
4122
|
+
]);
|
|
4123
|
+
useEffect8(() => {
|
|
4124
|
+
if (layout === ShellLayout.SPACE && !space) {
|
|
4125
|
+
log14.warn("No space found for shell space invitations.", void 0, {
|
|
4126
|
+
F: __dxlog_file14,
|
|
4127
|
+
L: 67,
|
|
4128
|
+
S: void 0,
|
|
4129
|
+
C: (f, a) => f(...a)
|
|
4130
|
+
});
|
|
4131
|
+
const timeout = setTimeout(async () => {
|
|
4132
|
+
await runtime.setAppContext({
|
|
4133
|
+
display: ShellDisplay.NONE
|
|
4134
|
+
});
|
|
4135
|
+
runtime.setLayout({
|
|
4136
|
+
layout: ShellLayout.DEFAULT
|
|
4137
|
+
});
|
|
4138
|
+
});
|
|
4139
|
+
return () => clearTimeout(timeout);
|
|
4140
|
+
}
|
|
4141
|
+
}, [
|
|
4142
|
+
runtime,
|
|
4143
|
+
layout,
|
|
4144
|
+
space
|
|
4145
|
+
]);
|
|
4146
|
+
switch (layout) {
|
|
4147
|
+
case ShellLayout.STATUS:
|
|
4148
|
+
return /* @__PURE__ */ React46.createElement(StatusDialog, null);
|
|
4149
|
+
case ShellLayout.INITIALIZE_IDENTITY:
|
|
4150
|
+
case ShellLayout.INITIALIZE_IDENTITY_FROM_INVITATION:
|
|
4151
|
+
case ShellLayout.INITIALIZE_IDENTITY_FROM_RECOVERY:
|
|
4152
|
+
return /* @__PURE__ */ React46.createElement(JoinDialog, {
|
|
4153
|
+
mode: "halo-only",
|
|
4154
|
+
initialDisposition: layout === ShellLayout.INITIALIZE_IDENTITY_FROM_RECOVERY ? "recover-identity" : layout === ShellLayout.INITIALIZE_IDENTITY_FROM_INVITATION ? "accept-halo-invitation" : "default",
|
|
4155
|
+
initialInvitationCode: invitationCode,
|
|
4156
|
+
onCancelResetStorage: () => runtime.setLayout({
|
|
4157
|
+
layout: ShellLayout.IDENTITY
|
|
4158
|
+
}),
|
|
4159
|
+
onDone: async () => {
|
|
4160
|
+
blurActiveElement();
|
|
4161
|
+
await runtime.setAppContext({
|
|
4162
|
+
display: ShellDisplay.NONE
|
|
4163
|
+
});
|
|
4164
|
+
runtime.setLayout({
|
|
4165
|
+
layout: ShellLayout.DEFAULT
|
|
4166
|
+
});
|
|
4167
|
+
}
|
|
4168
|
+
});
|
|
4169
|
+
case ShellLayout.IDENTITY:
|
|
4170
|
+
case ShellLayout.SHARE_IDENTITY:
|
|
4171
|
+
case ShellLayout.EDIT_PROFILE:
|
|
4172
|
+
return /* @__PURE__ */ React46.createElement(IdentityDialog, {
|
|
4173
|
+
createInvitationUrl: createDeviceInvitationUrl,
|
|
4174
|
+
onResetStorage: async () => {
|
|
4175
|
+
runtime.setLayout({
|
|
4176
|
+
layout: ShellLayout.STATUS
|
|
4177
|
+
});
|
|
4178
|
+
await client.reset();
|
|
4179
|
+
return runtime.setAppContext({
|
|
4180
|
+
display: ShellDisplay.NONE,
|
|
4181
|
+
reset: true
|
|
4182
|
+
});
|
|
4183
|
+
},
|
|
4184
|
+
onRecover: async () => {
|
|
4185
|
+
runtime.setLayout({
|
|
4186
|
+
layout: ShellLayout.STATUS
|
|
4187
|
+
});
|
|
4188
|
+
await client.reset();
|
|
4189
|
+
return runtime.setAppContext({
|
|
4190
|
+
display: ShellDisplay.NONE,
|
|
4191
|
+
reset: true,
|
|
4192
|
+
target: "recoverIdentity"
|
|
4193
|
+
});
|
|
4194
|
+
},
|
|
4195
|
+
onJoinNewIdentity: async () => {
|
|
4196
|
+
runtime.setLayout({
|
|
4197
|
+
layout: ShellLayout.STATUS
|
|
4198
|
+
});
|
|
4199
|
+
await client.reset();
|
|
4200
|
+
return runtime.setAppContext({
|
|
4201
|
+
display: ShellDisplay.NONE,
|
|
4202
|
+
reset: true,
|
|
4203
|
+
target: "deviceInvitation"
|
|
4204
|
+
});
|
|
4205
|
+
},
|
|
4206
|
+
onDone: async () => {
|
|
4207
|
+
blurActiveElement();
|
|
4208
|
+
await runtime.setAppContext({
|
|
4209
|
+
display: ShellDisplay.NONE
|
|
4210
|
+
});
|
|
4211
|
+
runtime.setLayout({
|
|
4212
|
+
layout: ShellLayout.DEFAULT
|
|
4213
|
+
});
|
|
4214
|
+
},
|
|
4215
|
+
initialDisposition: layout === ShellLayout.SHARE_IDENTITY ? "manage-device-invitation" : "default"
|
|
4216
|
+
});
|
|
4217
|
+
case ShellLayout.SPACE:
|
|
4218
|
+
return space ? /* @__PURE__ */ React46.createElement(SpaceDialog, {
|
|
4219
|
+
space,
|
|
4220
|
+
target,
|
|
4221
|
+
createInvitationUrl: createSpaceInvitationUrl,
|
|
4222
|
+
onDone: async () => {
|
|
4223
|
+
blurActiveElement();
|
|
4224
|
+
await runtime.setAppContext({
|
|
4225
|
+
display: ShellDisplay.NONE
|
|
4226
|
+
});
|
|
4227
|
+
runtime.setLayout({
|
|
4228
|
+
layout: ShellLayout.DEFAULT
|
|
4229
|
+
});
|
|
4230
|
+
}
|
|
4231
|
+
}) : null;
|
|
4232
|
+
case ShellLayout.JOIN_SPACE:
|
|
4233
|
+
return /* @__PURE__ */ React46.createElement(JoinDialog, {
|
|
4234
|
+
initialInvitationCode: invitationCode,
|
|
4235
|
+
onDone: async (result) => {
|
|
4236
|
+
blurActiveElement();
|
|
4237
|
+
const target2 = result?.target ?? void 0;
|
|
4238
|
+
await runtime.setAppContext({
|
|
4239
|
+
display: ShellDisplay.NONE,
|
|
4240
|
+
spaceKey: result?.spaceKey ?? void 0,
|
|
4241
|
+
target: target2
|
|
4242
|
+
});
|
|
4243
|
+
runtime.setLayout({
|
|
4244
|
+
layout: ShellLayout.DEFAULT
|
|
4245
|
+
});
|
|
4246
|
+
},
|
|
4247
|
+
onExit: async () => {
|
|
4248
|
+
blurActiveElement();
|
|
4249
|
+
await runtime.setAppContext({
|
|
4250
|
+
display: ShellDisplay.NONE
|
|
4251
|
+
});
|
|
4252
|
+
runtime.setLayout({
|
|
4253
|
+
layout: ShellLayout.DEFAULT
|
|
4254
|
+
});
|
|
4255
|
+
}
|
|
4256
|
+
});
|
|
4257
|
+
default:
|
|
4258
|
+
return null;
|
|
4259
|
+
}
|
|
4260
|
+
};
|
|
4261
|
+
|
|
4262
|
+
// packages/sdk/shell/src/composites/Shell/shell-runtime.ts
|
|
4263
|
+
import { Event } from "@dxos/async";
|
|
4264
|
+
import { appServiceBundle, shellServiceBundle } from "@dxos/client-protocol";
|
|
4265
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4266
|
+
import { ShellLayout as ShellLayout2 } from "@dxos/protocols/proto/dxos/iframe";
|
|
4267
|
+
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
4268
|
+
var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/composites/Shell/shell-runtime.ts";
|
|
4269
|
+
var ShellRuntimeImpl = class {
|
|
4270
|
+
constructor(_port) {
|
|
4271
|
+
this._port = _port;
|
|
4272
|
+
this.layoutUpdate = new Event();
|
|
4273
|
+
this.invitationUrlUpdate = new Event();
|
|
4274
|
+
this._layout = ShellLayout2.DEFAULT;
|
|
4275
|
+
this._invitationUrl = typeof window !== "undefined" ? window.location.origin : void 0;
|
|
4276
|
+
this._deviceInvitationParam = "deviceInvitationCode";
|
|
4277
|
+
this._spaceInvitationParam = "spaceInvitationCode";
|
|
4278
|
+
}
|
|
4279
|
+
get layout() {
|
|
4280
|
+
return this._layout;
|
|
4281
|
+
}
|
|
4282
|
+
get invitationCode() {
|
|
4283
|
+
return this._invitationCode;
|
|
4284
|
+
}
|
|
4285
|
+
/** @deprecated Use spaceId. */
|
|
4286
|
+
get spaceKey() {
|
|
4287
|
+
return this._spaceKey;
|
|
4288
|
+
}
|
|
4289
|
+
get spaceId() {
|
|
4290
|
+
return this._spaceId;
|
|
4291
|
+
}
|
|
4292
|
+
get invitationUrl() {
|
|
4293
|
+
return this._invitationUrl;
|
|
4294
|
+
}
|
|
4295
|
+
get deviceInvitationParam() {
|
|
4296
|
+
return this._deviceInvitationParam;
|
|
4297
|
+
}
|
|
4298
|
+
get spaceInvitationParam() {
|
|
4299
|
+
return this._spaceInvitationParam;
|
|
4300
|
+
}
|
|
4301
|
+
setLayout({ layout, invitationCode, spaceKey, spaceId }) {
|
|
4302
|
+
this._layout = layout;
|
|
4303
|
+
this._invitationCode = invitationCode;
|
|
4304
|
+
this._spaceKey = spaceKey;
|
|
4305
|
+
this._spaceId = spaceId;
|
|
4306
|
+
this.layoutUpdate.emit({
|
|
4307
|
+
layout,
|
|
4308
|
+
invitationCode,
|
|
4309
|
+
spaceKey,
|
|
4310
|
+
spaceId
|
|
4311
|
+
});
|
|
4312
|
+
}
|
|
4313
|
+
setInvitationUrl({ invitationUrl, deviceInvitationParam, spaceInvitationParam }) {
|
|
4314
|
+
this._invitationUrl = invitationUrl;
|
|
4315
|
+
this._deviceInvitationParam = deviceInvitationParam;
|
|
4316
|
+
this._spaceInvitationParam = spaceInvitationParam;
|
|
4317
|
+
this.invitationUrlUpdate.emit({
|
|
4318
|
+
invitationUrl,
|
|
4319
|
+
deviceInvitationParam,
|
|
4320
|
+
spaceInvitationParam
|
|
4321
|
+
});
|
|
4322
|
+
}
|
|
4323
|
+
async setAppContext(context) {
|
|
4324
|
+
invariant4(this._appRpc, "runtime not open", {
|
|
4325
|
+
F: __dxlog_file15,
|
|
4326
|
+
L: 83,
|
|
4327
|
+
S: this,
|
|
4328
|
+
A: [
|
|
4329
|
+
"this._appRpc",
|
|
4330
|
+
"'runtime not open'"
|
|
4331
|
+
]
|
|
4332
|
+
});
|
|
4333
|
+
await this._appRpc.rpc.AppService.setContext(context);
|
|
4334
|
+
}
|
|
4335
|
+
async open() {
|
|
4336
|
+
this._appRpc = createProtoRpcPeer({
|
|
4337
|
+
requested: appServiceBundle,
|
|
4338
|
+
exposed: shellServiceBundle,
|
|
4339
|
+
handlers: {
|
|
4340
|
+
ShellService: {
|
|
4341
|
+
setLayout: async (request) => {
|
|
4342
|
+
this._layout = request.layout;
|
|
4343
|
+
this._invitationCode = request.invitationCode;
|
|
4344
|
+
this._spaceKey = request.spaceKey;
|
|
4345
|
+
this._spaceId = request.spaceId;
|
|
4346
|
+
this.layoutUpdate.emit(request);
|
|
4347
|
+
},
|
|
4348
|
+
setInvitationUrl: async (request) => {
|
|
4349
|
+
this._invitationUrl = request.invitationUrl;
|
|
4350
|
+
this._deviceInvitationParam = request.deviceInvitationParam;
|
|
4351
|
+
this._spaceInvitationParam = request.spaceInvitationParam;
|
|
4352
|
+
this.invitationUrlUpdate.emit(request);
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
},
|
|
4356
|
+
port: this._port
|
|
4357
|
+
});
|
|
4358
|
+
await this._appRpc.open();
|
|
4359
|
+
}
|
|
4360
|
+
async close() {
|
|
4361
|
+
await this._appRpc?.close();
|
|
4362
|
+
this._appRpc = void 0;
|
|
4363
|
+
}
|
|
4364
|
+
};
|
|
4365
|
+
|
|
4366
|
+
// packages/sdk/shell/src/translations/locales/en-US.ts
|
|
4367
|
+
var en_US_exports = {};
|
|
4368
|
+
__export(en_US_exports, {
|
|
4369
|
+
os: () => os
|
|
4370
|
+
});
|
|
4371
|
+
var os = {
|
|
4372
|
+
"manage profile label": "Manage identity",
|
|
4373
|
+
"identity offline description": "Offline",
|
|
4374
|
+
"sidebar label": "DXOS sidebar",
|
|
4375
|
+
"copy invitation code label": "Copy URL",
|
|
4376
|
+
"copy success label": "Copied",
|
|
4377
|
+
"copy self public key label": "Copy public key",
|
|
4378
|
+
"open share panel label": "View QR code",
|
|
4379
|
+
"joining space heading": "Joining space",
|
|
4380
|
+
"join space heading": "Enter space invitation",
|
|
4381
|
+
"halo heading": "Initialize device identity",
|
|
4382
|
+
"exit label": "Exit",
|
|
4383
|
+
"identity selector title": "Join as",
|
|
4384
|
+
"identity radio group title": "Select an identity you\u2019ve associated with this device already",
|
|
4385
|
+
"add identity label": "Add",
|
|
4386
|
+
"continue label": "Continue",
|
|
4387
|
+
"back label": "Back",
|
|
4388
|
+
"next label": "Next",
|
|
4389
|
+
"close label": "Close",
|
|
4390
|
+
"auth choices label": "Choose an identity",
|
|
4391
|
+
"create identity label": "Create an identity",
|
|
4392
|
+
"create identity description": "Create a new identity.",
|
|
4393
|
+
"recover identity label": "Use a seed phrase",
|
|
4394
|
+
"recover identity description": "Enter your seed phrase to log in manually.",
|
|
4395
|
+
"join identity label": "Use another device",
|
|
4396
|
+
"join identity description": "Add this device to an identity you\u2019re already logged into on another device.",
|
|
4397
|
+
"deselect identity label": "Back to identities",
|
|
4398
|
+
"addition method chooser title": "An identity is required to continue",
|
|
4399
|
+
"new identity input label": "Set display name",
|
|
4400
|
+
"recover identity input label": "Type or paste your seed phrase",
|
|
4401
|
+
"failed to create identity message": "Failed to create an identity.",
|
|
4402
|
+
"failed to recover identity message": "Failed to recover an identity from the provided seed phrase.",
|
|
4403
|
+
"failed to authenticate message": "Incorrect code.",
|
|
4404
|
+
"identity added label": "Created identity & added to this device:",
|
|
4405
|
+
"join space as identity heading": "<part>as </part><part><icon/><label>{{labelValue}}</label></part>",
|
|
4406
|
+
"error status label": "Failed",
|
|
4407
|
+
"timeout status label": "Timed out",
|
|
4408
|
+
"cancelled status label": "Cancelled",
|
|
4409
|
+
"init status label": "Ready to connect",
|
|
4410
|
+
"connecting status label": "Connecting\u2026",
|
|
4411
|
+
"connected status label": "Enter authentication code",
|
|
4412
|
+
"authenticating status label": "Enter authentication code",
|
|
4413
|
+
"success status label": "Success",
|
|
4414
|
+
"cancel label": "Cancel",
|
|
4415
|
+
"done label": "Done",
|
|
4416
|
+
"reset label": "Start over",
|
|
4417
|
+
"auth code input label": "Enter the verification code",
|
|
4418
|
+
"invitation input label": "Paste an invitation code or URL",
|
|
4419
|
+
"create device invitation label": "Add device",
|
|
4420
|
+
"create space invitation label": "Invite",
|
|
4421
|
+
"qr label": "Scan to accept invitation",
|
|
4422
|
+
"empty invitations message": "No pending invitations",
|
|
4423
|
+
"empty device list message": "No devices authenticated other than this device.",
|
|
4424
|
+
"show all spaces label": "All spaces",
|
|
4425
|
+
"all spaces label": "All spaces",
|
|
4426
|
+
"create space label": "Create a new space",
|
|
4427
|
+
"join space label": "Join a space",
|
|
4428
|
+
"show current space label": "Current space",
|
|
4429
|
+
"view space invitations label": "View space invitations",
|
|
4430
|
+
"toggle sidebar label": "Open/close sidebar",
|
|
4431
|
+
"open sidebar label": "Open sidebar",
|
|
4432
|
+
"close sidebar label": "Close sidebar",
|
|
4433
|
+
"welcome message": "Welcome",
|
|
4434
|
+
"selecting identity heading": "Selecting identity",
|
|
4435
|
+
"devices heading": "Devices",
|
|
4436
|
+
"identity heading": "Profile settings",
|
|
4437
|
+
"choose add device label": "Add device",
|
|
4438
|
+
"choose devices label": "Manage devices",
|
|
4439
|
+
"choose profile label": "Edit profile",
|
|
4440
|
+
"choose sign out label": "Reset storage",
|
|
4441
|
+
"choose join new identity label": "Join existing device",
|
|
4442
|
+
"empty space members message": "There is nobody in this space yet.",
|
|
4443
|
+
"back to all invitations label": "Back to all invitations",
|
|
4444
|
+
"invitation heading": "Invitation",
|
|
4445
|
+
"invitation list heading": "Invitations",
|
|
4446
|
+
"device invitation list heading": "Pending device invitations",
|
|
4447
|
+
"space invitation list heading": "Pending invitations",
|
|
4448
|
+
"device list heading": "Devices",
|
|
4449
|
+
"space member list heading": "Members",
|
|
4450
|
+
"space panel heading": "Space membership",
|
|
4451
|
+
"auth code message": "Enter the following auth code on the joining device.",
|
|
4452
|
+
"auth other device emoji message": "Be sure the other device shows the following symbol:",
|
|
4453
|
+
"display name input label": "Display name",
|
|
4454
|
+
"display name input placeholder": "Enter a display name",
|
|
4455
|
+
"invite one label": "Single-use invitation",
|
|
4456
|
+
"invite one description": "Only one user may join.",
|
|
4457
|
+
"invite one qr label": "Single-use invitation",
|
|
4458
|
+
"invite one list item label": "Active single-use invitation",
|
|
4459
|
+
"invite many label": "Multi-use invitation",
|
|
4460
|
+
"invite many description": "Anyone with the link can join.",
|
|
4461
|
+
"invite many qr label": "Multi-use invitation",
|
|
4462
|
+
"invite many list item label": "Active multi-use invitation",
|
|
4463
|
+
"invite options label": "Change the active invite option.",
|
|
4464
|
+
"reset in progress label": "Resetting...",
|
|
4465
|
+
"confirm label": "Confirm",
|
|
4466
|
+
"reset storage input label": "WARNING: This will delete all data on this device. Type {{confirmationValue}} to continue.",
|
|
4467
|
+
"join new identity input label": "WARNING: To join an existing device all data on this device will be deleted. Type {{confirmationValue}} to continue.",
|
|
4468
|
+
"failed to reset identity message": "Failed to reset identity.",
|
|
4469
|
+
"confirmation value": "RESET",
|
|
4470
|
+
"confirmation placeholder": "Enter {{confirmationValue}} to continue.",
|
|
4471
|
+
"sign out chooser title": "Danger zone",
|
|
4472
|
+
"sign out chooser message": "Proceeding with the action below will erase all data on this device.",
|
|
4473
|
+
"join new identity label": "Join a new identity",
|
|
4474
|
+
"reset device label": "Reset storage",
|
|
4475
|
+
"reset device confirm message": "Are you sure you want to reset your device? All data will be lost.",
|
|
4476
|
+
"emoji and color label": "Emoji and color",
|
|
4477
|
+
"clear label": "Use default",
|
|
4478
|
+
"select emoji label": "Avatar emoji",
|
|
4479
|
+
"select hue label": "Avatar background color",
|
|
4480
|
+
"resetting message": "One moment while the device is reset\u2026",
|
|
4481
|
+
"red label": "Red",
|
|
4482
|
+
"orange label": "Orange",
|
|
4483
|
+
"amber label": "Amber",
|
|
4484
|
+
"yellow label": "Yellow",
|
|
4485
|
+
"lime label": "Lime",
|
|
4486
|
+
"green label": "Green",
|
|
4487
|
+
"emerald label": "Emerald",
|
|
4488
|
+
"teal label": "Teal",
|
|
4489
|
+
"cyan label": "Cyan",
|
|
4490
|
+
"sky label": "Sky",
|
|
4491
|
+
"blue label": "Blue",
|
|
4492
|
+
"indigo label": "Indigo",
|
|
4493
|
+
"violet label": "Violet",
|
|
4494
|
+
"purple label": "Purple",
|
|
4495
|
+
"fuchsia label": "Fuchsia",
|
|
4496
|
+
"pink label": "Pink",
|
|
4497
|
+
"rose label": "Rose",
|
|
4498
|
+
"current device tag label": "This device",
|
|
4499
|
+
"device name placeholder": "{{platform}} on {{os}}",
|
|
4500
|
+
"more options label": "More options",
|
|
4501
|
+
"disconnect label": "Go offline.",
|
|
4502
|
+
"connect label": "Go online.",
|
|
4503
|
+
"edit device label": "Edit device name & avatar",
|
|
4504
|
+
"agent heading": "Agent",
|
|
4505
|
+
"create agent clickwrap": 'By creating an agent, you agree to our <tosLink href="https://dxos.org/tos">Terms of\xA0Service</tosLink>.',
|
|
4506
|
+
"create agent description": "Creating an agent helps keep your devices and peers in-sync. An agent is like any other device, but since it\u2019s always online your changes will sync even when all your physical devices are\xA0asleep.",
|
|
4507
|
+
"create agent label": "Start an agent",
|
|
4508
|
+
"destroy agent label": "Shut down agent",
|
|
4509
|
+
"agent device label": "Your agent",
|
|
4510
|
+
"shell fallback title": "Shell failed to connect",
|
|
4511
|
+
"creating agent label": "Starting agent\u2026",
|
|
4512
|
+
"destroying agent label": "Stopping agent\u2026",
|
|
4513
|
+
"getting agent label": "Checking agent status\u2026",
|
|
4514
|
+
"agent requested label": "Agent requested",
|
|
4515
|
+
"agent requested description": "The agent service is creating an agent for you. Once the agent connects, it will display in the devices list.",
|
|
4516
|
+
"authenticating label": "Authenticating\u2026",
|
|
4517
|
+
"create recovery code label": "Create recovery code",
|
|
4518
|
+
"choose recover identity label": "Recover identity"
|
|
4519
|
+
};
|
|
4520
|
+
|
|
4521
|
+
// packages/sdk/shell/src/translations/index.ts
|
|
4522
|
+
var osTranslations = {
|
|
4523
|
+
"en-US": en_US_exports
|
|
4524
|
+
};
|
|
4525
|
+
|
|
4526
|
+
// packages/sdk/shell/src/composites/Shell/run-shell.tsx
|
|
4527
|
+
var runShell = async (config = new Config()) => {
|
|
4528
|
+
const runtime = new ShellRuntimeImpl(createIFramePort({
|
|
4529
|
+
channel: DEFAULT_SHELL_CHANNEL
|
|
4530
|
+
}));
|
|
4531
|
+
await runtime.open();
|
|
4532
|
+
try {
|
|
4533
|
+
const services = new ClientServicesProxy(createIFramePort({
|
|
4534
|
+
channel: DEFAULT_CLIENT_CHANNEL
|
|
4535
|
+
}));
|
|
4536
|
+
createRoot(document.getElementById("root")).render(/* @__PURE__ */ React47.createElement(StrictMode, null, /* @__PURE__ */ React47.createElement(ThemeProvider, {
|
|
4537
|
+
tx: defaultTx,
|
|
4538
|
+
resourceExtensions: [
|
|
4539
|
+
osTranslations
|
|
4540
|
+
]
|
|
4541
|
+
}, /* @__PURE__ */ React47.createElement(ClientProvider, {
|
|
4542
|
+
config,
|
|
4543
|
+
services,
|
|
4544
|
+
noBanner: true
|
|
4545
|
+
}, /* @__PURE__ */ React47.createElement(ClipboardProvider, null, /* @__PURE__ */ React47.createElement(Tooltip8.Provider, null, /* @__PURE__ */ React47.createElement(AgentHostingProvider, null, /* @__PURE__ */ React47.createElement(Shell, {
|
|
4546
|
+
runtime
|
|
4547
|
+
}))))))));
|
|
4548
|
+
} catch {
|
|
4549
|
+
createRoot(document.getElementById("root")).render(/* @__PURE__ */ React47.createElement(StrictMode, null, /* @__PURE__ */ React47.createElement(ThemeProvider, {
|
|
4550
|
+
tx: defaultTx,
|
|
4551
|
+
resourceExtensions: [
|
|
4552
|
+
osTranslations
|
|
4553
|
+
]
|
|
4554
|
+
}, /* @__PURE__ */ React47.createElement(Fallback, {
|
|
4555
|
+
onClose: () => runtime.setAppContext({
|
|
4556
|
+
display: ShellDisplay2.NONE
|
|
4557
|
+
})
|
|
4558
|
+
}))));
|
|
4559
|
+
}
|
|
4560
|
+
};
|
|
4561
|
+
var Fallback = ({ onClose }) => {
|
|
4562
|
+
const { t } = useTranslation26("os");
|
|
4563
|
+
return /* @__PURE__ */ React47.createElement(Dialog3.Root, {
|
|
4564
|
+
modal: true,
|
|
4565
|
+
open: true,
|
|
4566
|
+
onOpenChange: () => onClose?.()
|
|
4567
|
+
}, /* @__PURE__ */ React47.createElement(Dialog3.Overlay, null, /* @__PURE__ */ React47.createElement(Dialog3.Content, null, /* @__PURE__ */ React47.createElement(Dialog3.Title, null, t("shell fallback title")), /* @__PURE__ */ React47.createElement(Dialog3.Close, {
|
|
4568
|
+
asChild: true,
|
|
4569
|
+
onClick: () => onClose?.()
|
|
4570
|
+
}, /* @__PURE__ */ React47.createElement(Button11, {
|
|
4571
|
+
variant: "primary"
|
|
4572
|
+
}, t("close label"))))));
|
|
4573
|
+
};
|
|
4574
|
+
|
|
4575
|
+
// packages/sdk/shell/src/composites/Shell/ShellContext.tsx
|
|
4576
|
+
import React48, { createContext as createContext2, useCallback as useCallback8, useContext as useContext2, useEffect as useEffect9, useMemo as useMemo6, useState as useState15 } from "react";
|
|
4577
|
+
import { useClient as useClient10, ShellDisplay as ShellDisplay3, ShellLayout as ShellLayout4 } from "@dxos/react-client";
|
|
4578
|
+
import { useIdentity as useIdentity3 } from "@dxos/react-client/halo";
|
|
4579
|
+
import { mx as mx25 } from "@dxos/react-ui-theme";
|
|
4580
|
+
|
|
4581
|
+
// packages/sdk/shell/src/composites/Shell/memory-shell-runtime.ts
|
|
4582
|
+
import { Event as Event2 } from "@dxos/async";
|
|
4583
|
+
import { ShellLayout as ShellLayout3 } from "@dxos/react-client";
|
|
4584
|
+
var MemoryShellRuntime = class {
|
|
4585
|
+
constructor({ layout, invitationCode, spaceKey, invitationUrl, deviceInvitationParam, spaceInvitationParam } = {}) {
|
|
4586
|
+
this.layoutUpdate = new Event2();
|
|
4587
|
+
this.invitationUrlUpdate = new Event2();
|
|
4588
|
+
this.contextUpdate = new Event2();
|
|
4589
|
+
this._layout = layout ?? ShellLayout3.DEFAULT;
|
|
4590
|
+
this._invitationCode = invitationCode;
|
|
4591
|
+
this._spaceKey = spaceKey;
|
|
4592
|
+
this._invitationUrl = invitationUrl ?? window.location.origin;
|
|
4593
|
+
this._deviceInvitationParam = deviceInvitationParam ?? "deviceInvitationCode";
|
|
4594
|
+
this._spaceInvitationParam = spaceInvitationParam ?? "spaceInvitationCode";
|
|
4595
|
+
}
|
|
4596
|
+
get layout() {
|
|
4597
|
+
return this._layout;
|
|
4598
|
+
}
|
|
4599
|
+
get invitationCode() {
|
|
4600
|
+
return this._invitationCode;
|
|
4601
|
+
}
|
|
4602
|
+
get spaceKey() {
|
|
4603
|
+
return this._spaceKey;
|
|
4604
|
+
}
|
|
4605
|
+
get invitationUrl() {
|
|
4606
|
+
return this._invitationUrl;
|
|
4607
|
+
}
|
|
4608
|
+
get deviceInvitationParam() {
|
|
4609
|
+
return this._deviceInvitationParam;
|
|
4610
|
+
}
|
|
4611
|
+
get spaceInvitationParam() {
|
|
4612
|
+
return this._spaceInvitationParam;
|
|
4613
|
+
}
|
|
4614
|
+
setLayout(request) {
|
|
4615
|
+
this._layout = request.layout;
|
|
4616
|
+
this._invitationCode = request.invitationCode;
|
|
4617
|
+
this._spaceKey = request.spaceKey;
|
|
4618
|
+
this.layoutUpdate.emit(request);
|
|
4619
|
+
}
|
|
4620
|
+
setInvitationUrl(request) {
|
|
4621
|
+
this._invitationUrl = request.invitationUrl;
|
|
4622
|
+
this._deviceInvitationParam = request.deviceInvitationParam;
|
|
4623
|
+
this._spaceInvitationParam = request.spaceInvitationParam;
|
|
4624
|
+
this.invitationUrlUpdate.emit(request);
|
|
4625
|
+
}
|
|
4626
|
+
async setAppContext(context) {
|
|
4627
|
+
this.contextUpdate.emit(context);
|
|
4628
|
+
}
|
|
4629
|
+
};
|
|
4630
|
+
|
|
4631
|
+
// packages/sdk/shell/src/composites/Shell/ShellContext.tsx
|
|
4632
|
+
var ShellContext = /* @__PURE__ */ createContext2({});
|
|
4633
|
+
var useShell = () => {
|
|
4634
|
+
const client = useClient10();
|
|
4635
|
+
const { runtime, setDisplay } = useContext2(ShellContext);
|
|
4636
|
+
const setLayout = async (layout, options) => {
|
|
4637
|
+
if (runtime) {
|
|
4638
|
+
if (layout === ShellLayout4.DEFAULT) {
|
|
4639
|
+
setDisplay?.(ShellDisplay3.NONE);
|
|
4640
|
+
} else {
|
|
4641
|
+
setDisplay?.(ShellDisplay3.FULLSCREEN);
|
|
4642
|
+
}
|
|
4643
|
+
runtime.setLayout({
|
|
4644
|
+
layout,
|
|
4645
|
+
...options
|
|
4646
|
+
});
|
|
4647
|
+
}
|
|
4648
|
+
await client.shell.open(layout, options);
|
|
4649
|
+
};
|
|
4650
|
+
return {
|
|
4651
|
+
setLayout
|
|
4652
|
+
};
|
|
4653
|
+
};
|
|
4654
|
+
var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoinedSpace, children }) => {
|
|
4655
|
+
const client = useClient10();
|
|
4656
|
+
const identity = useIdentity3();
|
|
4657
|
+
const [display, setDisplay] = useState15(!identity || spaceInvitationCode || deviceInvitationCode ? ShellDisplay3.FULLSCREEN : ShellDisplay3.NONE);
|
|
4658
|
+
const shellRuntime = useMemo6(() => {
|
|
4659
|
+
if (client.config.get("runtime.app.env.DX_VAULT") !== "false") {
|
|
4660
|
+
return;
|
|
4661
|
+
}
|
|
4662
|
+
if (spaceInvitationCode) {
|
|
4663
|
+
return new MemoryShellRuntime({
|
|
4664
|
+
layout: ShellLayout4.JOIN_SPACE,
|
|
4665
|
+
invitationCode: spaceInvitationCode
|
|
4666
|
+
});
|
|
4667
|
+
}
|
|
4668
|
+
if (deviceInvitationCode) {
|
|
4669
|
+
return new MemoryShellRuntime({
|
|
4670
|
+
layout: ShellLayout4.INITIALIZE_IDENTITY,
|
|
4671
|
+
invitationCode: deviceInvitationCode
|
|
4672
|
+
});
|
|
4673
|
+
}
|
|
4674
|
+
return new MemoryShellRuntime({
|
|
4675
|
+
layout: identity ? ShellLayout4.DEFAULT : ShellLayout4.INITIALIZE_IDENTITY
|
|
4676
|
+
});
|
|
4677
|
+
}, [
|
|
4678
|
+
client,
|
|
4679
|
+
identity,
|
|
4680
|
+
spaceInvitationCode,
|
|
4681
|
+
deviceInvitationCode
|
|
4682
|
+
]);
|
|
4683
|
+
const handleKeyDown = useCallback8((event) => {
|
|
4684
|
+
if (!space || !shellRuntime) {
|
|
4685
|
+
return;
|
|
4686
|
+
}
|
|
4687
|
+
const modifier = event.ctrlKey || event.metaKey;
|
|
4688
|
+
if (event.key === ">" && event.shiftKey && modifier) {
|
|
4689
|
+
shellRuntime.setLayout({
|
|
4690
|
+
layout: ShellLayout4.SHARE_IDENTITY
|
|
4691
|
+
});
|
|
4692
|
+
setDisplay(ShellDisplay3.FULLSCREEN);
|
|
4693
|
+
} else if (event.key === "." && modifier) {
|
|
4694
|
+
shellRuntime.setLayout({
|
|
4695
|
+
layout: ShellLayout4.SPACE,
|
|
4696
|
+
spaceKey: space.key
|
|
4697
|
+
});
|
|
4698
|
+
setDisplay(ShellDisplay3.FULLSCREEN);
|
|
4699
|
+
}
|
|
4700
|
+
}, [
|
|
4701
|
+
space,
|
|
4702
|
+
shellRuntime
|
|
4703
|
+
]);
|
|
4704
|
+
useEffect9(() => {
|
|
4705
|
+
if (!shellRuntime) {
|
|
4706
|
+
return;
|
|
4707
|
+
}
|
|
4708
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4709
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4710
|
+
}, [
|
|
4711
|
+
shellRuntime,
|
|
4712
|
+
handleKeyDown
|
|
4713
|
+
]);
|
|
4714
|
+
useEffect9(() => {
|
|
4715
|
+
if (!shellRuntime) {
|
|
4716
|
+
return;
|
|
4717
|
+
}
|
|
4718
|
+
return shellRuntime.contextUpdate.on(({ display: display2, spaceKey }) => {
|
|
4719
|
+
if (display2) {
|
|
4720
|
+
setDisplay(display2);
|
|
4721
|
+
}
|
|
4722
|
+
onJoinedSpace?.(spaceKey);
|
|
4723
|
+
});
|
|
4724
|
+
}, [
|
|
4725
|
+
shellRuntime
|
|
4726
|
+
]);
|
|
4727
|
+
return /* @__PURE__ */ React48.createElement(React48.Fragment, null, shellRuntime && /* @__PURE__ */ React48.createElement("div", {
|
|
4728
|
+
className: mx25(display === ShellDisplay3.NONE ? "hidden" : "")
|
|
4729
|
+
}, /* @__PURE__ */ React48.createElement(Shell, {
|
|
4730
|
+
runtime: shellRuntime
|
|
4731
|
+
})), /* @__PURE__ */ React48.createElement(ShellContext.Provider, {
|
|
4732
|
+
value: {
|
|
4733
|
+
runtime: shellRuntime,
|
|
4734
|
+
setDisplay
|
|
4735
|
+
}
|
|
4736
|
+
}, children));
|
|
4737
|
+
};
|
|
4738
|
+
export {
|
|
4739
|
+
Action,
|
|
4740
|
+
Actions,
|
|
4741
|
+
AgentConfig,
|
|
4742
|
+
AuthCode,
|
|
4743
|
+
BifurcatedAction,
|
|
4744
|
+
Centered,
|
|
4745
|
+
ClipboardContext,
|
|
4746
|
+
ClipboardProvider,
|
|
4747
|
+
CloseButton,
|
|
4748
|
+
CompoundButton,
|
|
4749
|
+
ConfirmReset,
|
|
4750
|
+
ConfirmResetImpl,
|
|
4751
|
+
CopyButton,
|
|
4752
|
+
CopyButtonIconOnly,
|
|
4753
|
+
DeviceList,
|
|
4754
|
+
Emoji,
|
|
4755
|
+
EmojiPickerBlock,
|
|
4756
|
+
EmojiPickerToolbarButton,
|
|
4757
|
+
Heading,
|
|
4758
|
+
HuePickerBlock,
|
|
4759
|
+
HuePickerToolbarButton,
|
|
4760
|
+
IdentityDialog,
|
|
4761
|
+
IdentityListItem,
|
|
4762
|
+
IdentityPanel,
|
|
4763
|
+
IdentityPanelImpl,
|
|
4764
|
+
Input,
|
|
4765
|
+
InvitationList,
|
|
4766
|
+
InvitationListContainer,
|
|
4767
|
+
InvitationListItem,
|
|
4768
|
+
InvitationListItemImpl,
|
|
4769
|
+
InvitationManager,
|
|
4770
|
+
JoinDialog,
|
|
4771
|
+
JoinPanel,
|
|
4772
|
+
JoinPanelImpl,
|
|
4773
|
+
Label,
|
|
4774
|
+
Shell,
|
|
4775
|
+
ShellContext,
|
|
4776
|
+
ShellProvider,
|
|
4777
|
+
SpaceDialog,
|
|
4778
|
+
SpaceListItem,
|
|
4779
|
+
SpaceMemberList,
|
|
4780
|
+
SpaceMemberListImpl,
|
|
4781
|
+
SpacePanel,
|
|
4782
|
+
SpacePanelImpl,
|
|
4783
|
+
StatusPanel,
|
|
4784
|
+
StepHeading,
|
|
4785
|
+
Viewport,
|
|
4786
|
+
activeBgColor,
|
|
4787
|
+
activeStrokeColor,
|
|
4788
|
+
activeTextColor,
|
|
4789
|
+
cancelledBgColor,
|
|
4790
|
+
cancelledStrokeColor,
|
|
4791
|
+
cancelledTextColor,
|
|
4792
|
+
createViewportScope,
|
|
4793
|
+
errorBgColor,
|
|
4794
|
+
errorStrokeColor,
|
|
4795
|
+
errorTextColor,
|
|
4796
|
+
inactiveBgColor,
|
|
4797
|
+
inactiveStrokeColor,
|
|
4798
|
+
inactiveTextColor,
|
|
4799
|
+
osTranslations,
|
|
4800
|
+
resolvedBgColor,
|
|
4801
|
+
resolvedStrokeColor,
|
|
4802
|
+
resolvedTextColor,
|
|
4803
|
+
runShell,
|
|
4804
|
+
stepStyles,
|
|
4805
|
+
successBgColor,
|
|
4806
|
+
successStrokeColor,
|
|
4807
|
+
successTextColor,
|
|
4808
|
+
useClipboardContext,
|
|
4809
|
+
useShell,
|
|
4810
|
+
useViewportContext
|
|
4811
|
+
};
|
|
4812
|
+
//# sourceMappingURL=react.mjs.map
|