reflet-sdk 0.7.6 → 0.7.8
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/CHANGELOG.md +34 -0
- package/README.md +15 -6
- package/dist/desktop.d.ts.map +1 -1
- package/dist/desktop.js +3 -2
- package/dist/desktop.js.map +1 -1
- package/dist/devtools-layer-B_b_3MH3.js +372 -0
- package/dist/devtools-layer-B_b_3MH3.js.map +1 -0
- package/dist/devtools-next.js +1 -1
- package/dist/devtools-vite.js +3 -3
- package/dist/feedback.js +4 -5
- package/dist/feedback.js.map +1 -1
- package/dist/{handler-ndF3gZBx.js → handler-D8c3woEz.js} +3 -3
- package/dist/{handler-ndF3gZBx.js.map → handler-D8c3woEz.js.map} +1 -1
- package/dist/{protocol-cJVVwnPe.js → protocol-ClxYWmhu.js} +2 -2
- package/dist/{protocol-cJVVwnPe.js.map → protocol-ClxYWmhu.js.map} +1 -1
- package/dist/{reflet-proxy-BW6q9xds.js → reflet-proxy-Dg6mea-4.js} +14 -7
- package/dist/reflet-proxy-Dg6mea-4.js.map +1 -0
- package/dist/{submit-DsJwTy3X.js → submit-D_DrRBeB.js} +49 -3
- package/dist/submit-D_DrRBeB.js.map +1 -0
- package/dist/{team-layer-VlQtvR5O.js → team-layer-CxMBo9WN.js} +162 -33
- package/dist/team-layer-CxMBo9WN.js.map +1 -0
- package/dist/{devtools-styles-DQpiubGB.js → use-sheet-tab-azUezLAq.js} +5261 -1573
- package/dist/use-sheet-tab-azUezLAq.js.map +1 -0
- package/package.json +1 -1
- package/dist/devtools-layer-xN47FKpW.js +0 -3818
- package/dist/devtools-layer-xN47FKpW.js.map +0 -1
- package/dist/devtools-styles-DQpiubGB.js.map +0 -1
- package/dist/reflet-proxy-BW6q9xds.js.map +0 -1
- package/dist/selection-outline-NzAAAZXR.js +0 -51
- package/dist/selection-outline-NzAAAZXR.js.map +0 -1
- package/dist/submit-DsJwTy3X.js.map +0 -1
- package/dist/team-layer-VlQtvR5O.js.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { d as SelectionOutline } from "./submit-D_DrRBeB.js";
|
|
1
2
|
import { r as teamAccessStorageKey, t as TEAM_ACTIVATION_PARAM } from "./team-activation-Cv5U7OF1.js";
|
|
2
|
-
import { B as
|
|
3
|
+
import { A as sessionSheetPlace, B as teamTransport, C as AccountFooter, F as useWorkspaceLoader, G as SessionApiError, I as purgeAccount, J as reportFailure, K as sessionApiErrorSchema, L as bridgeBoardCall, M as RecordingLayer, N as SessionWorkspaceProvider, O as SESSIONS_STYLES, P as failureMessage, R as bridgeTransport, S as InboxPanel, _ as DevtoolsBarButtons, a as NotePicker, d as useNotes, g as DevtoolsBar, h as DevtoolsSheet, i as NotesPanel, j as useSessionNavigation, k as SessionsPanel, m as DEVTOOLS_STYLES, n as useSheetTab, p as usePageHighlight, q as Notices, r as NotePins, u as unsentNoteCount, y as SessionsBarButton } from "./use-sheet-tab-azUezLAq.js";
|
|
3
4
|
import { z } from "zod";
|
|
4
|
-
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
//#region src/sessions/team/team-auth.ts
|
|
7
8
|
const RETURN_CODE_PARAM = "reflet-team-code";
|
|
@@ -270,13 +271,20 @@ function TeamSignInCard({ isFinishing, notice, onSignIn, continuesInBrowser }) {
|
|
|
270
271
|
});
|
|
271
272
|
}
|
|
272
273
|
//#endregion
|
|
273
|
-
//#region src/sessions/team/team-
|
|
274
|
+
//#region src/sessions/team/team-tools.tsx
|
|
274
275
|
const TEAM_TOOLS_LABEL = "Reflet team tools";
|
|
275
276
|
const REFUSED_SIGN_IN_COPY = "Reflet no longer accepts this sign-in. Sign in again to record.";
|
|
276
|
-
|
|
277
|
+
const SESSIONS_TABS = ["sessions"];
|
|
278
|
+
const BOARD_TABS = [
|
|
279
|
+
"inbox",
|
|
280
|
+
"notes",
|
|
281
|
+
"sessions"
|
|
282
|
+
];
|
|
283
|
+
function SessionsBody({ navigation, onStarted, onWriteNote, state }) {
|
|
277
284
|
if (state.kind === "ready") return /* @__PURE__ */ jsx(SessionsPanel, {
|
|
278
285
|
navigation,
|
|
279
|
-
onStarted
|
|
286
|
+
onStarted,
|
|
287
|
+
onWriteNote
|
|
280
288
|
});
|
|
281
289
|
if (state.kind === "failed") return /* @__PURE__ */ jsxs("div", {
|
|
282
290
|
className: "dt-empty",
|
|
@@ -293,9 +301,9 @@ function SessionsBody({ navigation, onStarted, state }) {
|
|
|
293
301
|
children: "Opening your sessions…"
|
|
294
302
|
});
|
|
295
303
|
}
|
|
296
|
-
function TeamSheet({ account, navigation, onClose, side }) {
|
|
304
|
+
function TeamSheet({ account, children, navigation, onClose, onSelectTab, side, tab, tabs }) {
|
|
297
305
|
const { state } = account;
|
|
298
|
-
const place = state.kind === "ready" ? sessionSheetPlace(navigation) : null;
|
|
306
|
+
const place = tab === "sessions" && state.kind === "ready" ? sessionSheetPlace(navigation) : null;
|
|
299
307
|
return /* @__PURE__ */ jsx(DevtoolsSheet, {
|
|
300
308
|
footer: place === null && /* @__PURE__ */ jsx(AccountFooter, {
|
|
301
309
|
actions: [{
|
|
@@ -307,18 +315,22 @@ function TeamSheet({ account, navigation, onClose, side }) {
|
|
|
307
315
|
}),
|
|
308
316
|
label: TEAM_TOOLS_LABEL,
|
|
309
317
|
navigation: {
|
|
310
|
-
onSelectTab
|
|
318
|
+
onSelectTab,
|
|
311
319
|
place,
|
|
312
|
-
tab
|
|
313
|
-
tabs
|
|
320
|
+
tab,
|
|
321
|
+
tabs
|
|
314
322
|
},
|
|
315
323
|
onClose,
|
|
316
324
|
side,
|
|
317
|
-
children
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
325
|
+
children
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function TeamBar({ children, organizationName, placement }) {
|
|
329
|
+
return /* @__PURE__ */ jsx(DevtoolsBar, {
|
|
330
|
+
edge: placement.edge,
|
|
331
|
+
label: `${TEAM_TOOLS_LABEL} · ${organizationName}`,
|
|
332
|
+
side: placement.side,
|
|
333
|
+
children
|
|
322
334
|
});
|
|
323
335
|
}
|
|
324
336
|
function useTeamWorkspace(team) {
|
|
@@ -334,32 +346,39 @@ function useTeamWorkspace(team) {
|
|
|
334
346
|
onSignOut(null);
|
|
335
347
|
};
|
|
336
348
|
return {
|
|
337
|
-
|
|
338
|
-
|
|
349
|
+
account: {
|
|
350
|
+
onSignOut: signOut,
|
|
351
|
+
organizationName: team.organizationName,
|
|
352
|
+
state
|
|
353
|
+
},
|
|
339
354
|
workspace
|
|
340
355
|
};
|
|
341
356
|
}
|
|
342
|
-
function
|
|
343
|
-
const {
|
|
357
|
+
function SessionsTeamTools({ placement, team }) {
|
|
358
|
+
const { account, workspace } = useTeamWorkspace(team);
|
|
344
359
|
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
345
360
|
const navigation = useSessionNavigation();
|
|
361
|
+
const closeSheet = () => setIsSheetOpen(false);
|
|
346
362
|
return /* @__PURE__ */ jsxs(SessionWorkspaceProvider, {
|
|
347
363
|
workspace,
|
|
348
364
|
children: [
|
|
349
365
|
isSheetOpen && /* @__PURE__ */ jsx(TeamSheet, {
|
|
350
|
-
account
|
|
351
|
-
onSignOut: signOut,
|
|
352
|
-
organizationName: team.organizationName,
|
|
353
|
-
state
|
|
354
|
-
},
|
|
366
|
+
account,
|
|
355
367
|
navigation,
|
|
356
|
-
onClose:
|
|
357
|
-
|
|
358
|
-
}),
|
|
359
|
-
/* @__PURE__ */ jsx(DevtoolsBar, {
|
|
360
|
-
edge: placement.edge,
|
|
361
|
-
label: TEAM_TOOLS_LABEL,
|
|
368
|
+
onClose: closeSheet,
|
|
369
|
+
onSelectTab: () => void 0,
|
|
362
370
|
side: placement.side,
|
|
371
|
+
tab: "sessions",
|
|
372
|
+
tabs: SESSIONS_TABS,
|
|
373
|
+
children: /* @__PURE__ */ jsx(SessionsBody, {
|
|
374
|
+
navigation,
|
|
375
|
+
onStarted: closeSheet,
|
|
376
|
+
state: account.state
|
|
377
|
+
})
|
|
378
|
+
}),
|
|
379
|
+
/* @__PURE__ */ jsx(TeamBar, {
|
|
380
|
+
organizationName: team.organizationName,
|
|
381
|
+
placement,
|
|
363
382
|
children: /* @__PURE__ */ jsx(SessionsBarButton, { onOpen: () => setIsSheetOpen(true) })
|
|
364
383
|
}),
|
|
365
384
|
workspace && /* @__PURE__ */ jsx(RecordingLayer, { onFinished: (target) => {
|
|
@@ -372,6 +391,102 @@ function TeamTools({ team, placement }) {
|
|
|
372
391
|
]
|
|
373
392
|
});
|
|
374
393
|
}
|
|
394
|
+
/** The devtools panel minus what needs the source code: no Code tab, no source lookup. */
|
|
395
|
+
function BoardTeamTools({ boardCall, placement, team }) {
|
|
396
|
+
const { account, workspace } = useTeamWorkspace(team);
|
|
397
|
+
const sheet = useSheetTab();
|
|
398
|
+
const { openTab } = sheet;
|
|
399
|
+
const navigation = useSessionNavigation();
|
|
400
|
+
const notes = useNotes();
|
|
401
|
+
const { clearHighlight, highlighted, showSelector } = usePageHighlight();
|
|
402
|
+
const [isPicking, setIsPicking] = useState(false);
|
|
403
|
+
const startPick = useCallback(() => setIsPicking(true), []);
|
|
404
|
+
const stopPick = useCallback(() => setIsPicking(false), []);
|
|
405
|
+
const closeSheet = () => {
|
|
406
|
+
sheet.close();
|
|
407
|
+
clearHighlight();
|
|
408
|
+
};
|
|
409
|
+
const openPanel = (tab) => sheet.select(tab ?? (BOARD_TABS.includes(sheet.lastTab) ? sheet.lastTab : "inbox"));
|
|
410
|
+
const writeNoteFromSession = () => {
|
|
411
|
+
closeSheet();
|
|
412
|
+
startPick();
|
|
413
|
+
};
|
|
414
|
+
return /* @__PURE__ */ jsx(SessionWorkspaceProvider, {
|
|
415
|
+
workspace,
|
|
416
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
417
|
+
className: "dt",
|
|
418
|
+
"data-recessed": isPicking,
|
|
419
|
+
children: [
|
|
420
|
+
/* @__PURE__ */ jsx(NotePins, {
|
|
421
|
+
isVisible: !isPicking,
|
|
422
|
+
notes
|
|
423
|
+
}),
|
|
424
|
+
openTab && /* @__PURE__ */ jsxs(TeamSheet, {
|
|
425
|
+
account,
|
|
426
|
+
navigation,
|
|
427
|
+
onClose: closeSheet,
|
|
428
|
+
onSelectTab: sheet.select,
|
|
429
|
+
side: placement.side,
|
|
430
|
+
tab: openTab,
|
|
431
|
+
tabs: BOARD_TABS,
|
|
432
|
+
children: [
|
|
433
|
+
openTab === "inbox" && /* @__PURE__ */ jsx(InboxPanel, {
|
|
434
|
+
boardCall,
|
|
435
|
+
onShowSelector: showSelector
|
|
436
|
+
}),
|
|
437
|
+
openTab === "notes" && /* @__PURE__ */ jsx(NotesPanel, {
|
|
438
|
+
boardCall,
|
|
439
|
+
notes,
|
|
440
|
+
onPick: startPick,
|
|
441
|
+
onShowSelector: showSelector,
|
|
442
|
+
sendBlockedReason: null
|
|
443
|
+
}),
|
|
444
|
+
openTab === "sessions" && /* @__PURE__ */ jsx(SessionsBody, {
|
|
445
|
+
navigation,
|
|
446
|
+
onStarted: closeSheet,
|
|
447
|
+
onWriteNote: writeNoteFromSession,
|
|
448
|
+
state: account.state
|
|
449
|
+
})
|
|
450
|
+
]
|
|
451
|
+
}),
|
|
452
|
+
/* @__PURE__ */ jsx(TeamBar, {
|
|
453
|
+
organizationName: team.organizationName,
|
|
454
|
+
placement,
|
|
455
|
+
children: /* @__PURE__ */ jsx(DevtoolsBarButtons, {
|
|
456
|
+
canOpenCode: false,
|
|
457
|
+
onOpen: openPanel,
|
|
458
|
+
onPick: startPick,
|
|
459
|
+
unsentNoteCount: unsentNoteCount(notes)
|
|
460
|
+
})
|
|
461
|
+
}),
|
|
462
|
+
openTab && /* @__PURE__ */ jsx(SelectionOutline, { node: highlighted }),
|
|
463
|
+
workspace && /* @__PURE__ */ jsx(RecordingLayer, { onFinished: (target) => {
|
|
464
|
+
navigation.go({
|
|
465
|
+
target,
|
|
466
|
+
view: "review"
|
|
467
|
+
});
|
|
468
|
+
sheet.select("sessions");
|
|
469
|
+
} }),
|
|
470
|
+
isPicking && /* @__PURE__ */ jsx(NotePicker, {
|
|
471
|
+
canReadSource: false,
|
|
472
|
+
onDone: stopPick
|
|
473
|
+
})
|
|
474
|
+
]
|
|
475
|
+
})
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function TeamTools({ placement, team }) {
|
|
479
|
+
return team.boardCall ? /* @__PURE__ */ jsx(BoardTeamTools, {
|
|
480
|
+
boardCall: team.boardCall,
|
|
481
|
+
placement,
|
|
482
|
+
team
|
|
483
|
+
}) : /* @__PURE__ */ jsx(SessionsTeamTools, {
|
|
484
|
+
placement,
|
|
485
|
+
team
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/sessions/team/team-layer.tsx
|
|
375
490
|
function SignedOutAnchor({ children, placement }) {
|
|
376
491
|
return /* @__PURE__ */ jsx("div", {
|
|
377
492
|
className: "dt-team-anchor",
|
|
@@ -410,6 +525,7 @@ function BrowserTeamAccount({ connection, placement }) {
|
|
|
410
525
|
if (access && transport) return /* @__PURE__ */ jsx(TeamTools, {
|
|
411
526
|
placement,
|
|
412
527
|
team: {
|
|
528
|
+
boardCall: null,
|
|
413
529
|
onSignOut: signOut,
|
|
414
530
|
organizationName: access.organizationName,
|
|
415
531
|
transport
|
|
@@ -425,6 +541,17 @@ function BrowserTeamAccount({ connection, placement }) {
|
|
|
425
541
|
})
|
|
426
542
|
});
|
|
427
543
|
}
|
|
544
|
+
/** The host already dropped a token Reflet refuses, so later calls would only fail. */
|
|
545
|
+
function signsOutWhenRefused(boardCall, onRefused) {
|
|
546
|
+
return async (apiPath, init) => {
|
|
547
|
+
try {
|
|
548
|
+
return await boardCall(apiPath, init);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
if (error instanceof SessionApiError && error.status === 401) onRefused();
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
428
555
|
/** A desktop app signs in through the system browser; its privileged process keeps the credential. */
|
|
429
556
|
function BridgeTeamAccount({ bridge, placement }) {
|
|
430
557
|
const [accountState, setAccountState] = useState({ kind: "loading" });
|
|
@@ -456,18 +583,20 @@ function BridgeTeamAccount({ bridge, placement }) {
|
|
|
456
583
|
});
|
|
457
584
|
setNotice(null);
|
|
458
585
|
};
|
|
459
|
-
const signOut = (reason) => {
|
|
586
|
+
const signOut = useCallback((reason) => {
|
|
460
587
|
setAccountState({
|
|
461
588
|
account: null,
|
|
462
589
|
kind: "loaded"
|
|
463
590
|
});
|
|
464
591
|
setNotice(reason);
|
|
465
592
|
bridge.signOut().catch((error) => reportFailure("Signing out of Reflet did not finish", error));
|
|
466
|
-
};
|
|
593
|
+
}, [bridge]);
|
|
594
|
+
const boardCall = useMemo(() => signsOutWhenRefused(bridgeBoardCall(bridge), () => signOut(REFUSED_SIGN_IN_COPY)), [bridge, signOut]);
|
|
467
595
|
if (accountState.kind === "loading") return null;
|
|
468
596
|
if (accountState.account) return /* @__PURE__ */ jsx(TeamTools, {
|
|
469
597
|
placement,
|
|
470
598
|
team: {
|
|
599
|
+
boardCall,
|
|
471
600
|
onSignOut: signOut,
|
|
472
601
|
organizationName: accountState.account.organizationName,
|
|
473
602
|
transport
|
|
@@ -509,4 +638,4 @@ function TeamLayer(props) {
|
|
|
509
638
|
//#endregion
|
|
510
639
|
export { TeamLayer };
|
|
511
640
|
|
|
512
|
-
//# sourceMappingURL=team-layer-
|
|
641
|
+
//# sourceMappingURL=team-layer-CxMBo9WN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-layer-CxMBo9WN.js","names":[],"sources":["../src/sessions/team/team-auth.ts","../src/sessions/team/team-sign-in-card.tsx","../src/sessions/team/team-tools.tsx","../src/sessions/team/team-layer.tsx"],"sourcesContent":["import { z } from \"zod\";\nimport { sessionApiErrorSchema } from \"../protocol\";\nimport { TEAM_ACTIVATION_PARAM, teamAccessStorageKey } from \"./team-activation\";\n\nconst RETURN_CODE_PARAM = \"reflet-team-code\";\nconst RETURN_ERROR_PARAM = \"reflet-team-error\";\nconst RETURN_STATE_PARAM = \"reflet-team-state\";\nconst RETURN_PARAMS = [\n RETURN_CODE_PARAM,\n RETURN_ERROR_PARAM,\n RETURN_STATE_PARAM,\n];\nconst PENDING_SIGN_IN_PREFIX = \"reflet-team-sign-in:\";\nconst PKCE_RANDOM_BYTES = 32;\nconst TRAILING_SLASHES = /\\/+$/;\nconst BASE64_PADDING = /[=]+$/;\n\nconst teamAccessSchema = z.object({\n expiresAt: z.number(),\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_team_\"),\n});\n\nexport type TeamAccess = z.infer<typeof teamAccessSchema>;\n\nconst pendingSignInSchema = z.object({\n codeVerifier: z.string(),\n state: z.string(),\n});\n\ntype PendingSignIn = z.infer<typeof pendingSignInSchema>;\n\nconst SIGN_IN_FAILURE_MESSAGES = {\n cancelled: \"Sign-in was cancelled.\",\n exchange_failed: \"Couldn't finish signing in to Reflet. Try again.\",\n interrupted:\n \"This sign-in was started in another tab or has expired. Sign in again.\",\n storage_blocked:\n \"Your browser blocks storage for this site, so Reflet sign-in can't finish. Allow site data, then try again.\",\n} as const;\n\nexport type TeamSignInFailure = keyof typeof SIGN_IN_FAILURE_MESSAGES;\n\nexport class TeamSignInError extends Error {\n readonly reason: TeamSignInFailure;\n\n constructor(reason: TeamSignInFailure, message?: string) {\n super(message ?? SIGN_IN_FAILURE_MESSAGES[reason]);\n this.name = \"TeamSignInError\";\n this.reason = reason;\n }\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n return btoa(String.fromCharCode(...bytes))\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(BASE64_PADDING, \"\");\n}\n\nfunction randomBase64Url(): string {\n return base64Url(crypto.getRandomValues(new Uint8Array(PKCE_RANDOM_BYTES)));\n}\n\nasync function pkceChallengeFor(codeVerifier: string): Promise<string> {\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(codeVerifier)\n );\n return base64Url(new Uint8Array(digest));\n}\n\nfunction apiEndpoint(apiUrl: string, path: string): string {\n return `${apiUrl.replace(TRAILING_SLASHES, \"\")}${path}`;\n}\n\nfunction parseStoredJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nfunction storedTeamAccess(publicKey: string): TeamAccess | null {\n try {\n const raw = localStorage.getItem(teamAccessStorageKey(publicKey));\n const parsed = teamAccessSchema.safeParse(\n raw === null ? null : parseStoredJson(raw)\n );\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nfunction persistTeamAccess(publicKey: string, access: TeamAccess | null): void {\n try {\n if (access) {\n localStorage.setItem(\n teamAccessStorageKey(publicKey),\n JSON.stringify(access)\n );\n } else {\n localStorage.removeItem(teamAccessStorageKey(publicKey));\n }\n } catch {\n // Storage disabled by browser policy: access then only lasts for this page.\n }\n}\n\nexport function readTeamAccess(publicKey: string): TeamAccess | null {\n const access = storedTeamAccess(publicKey);\n if (access && access.expiresAt > Date.now()) {\n return access;\n }\n persistTeamAccess(publicKey, null);\n return null;\n}\n\nfunction pendingSignInKey(publicKey: string): string {\n return `${PENDING_SIGN_IN_PREFIX}${publicKey}`;\n}\n\nfunction takePendingSignIn(publicKey: string): PendingSignIn | null {\n try {\n const key = pendingSignInKey(publicKey);\n const raw = sessionStorage.getItem(key);\n sessionStorage.removeItem(key);\n const parsed = pendingSignInSchema.safeParse(\n raw === null ? null : parseStoredJson(raw)\n );\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nfunction rememberPendingSignIn(publicKey: string, pending: PendingSignIn) {\n try {\n sessionStorage.setItem(\n pendingSignInKey(publicKey),\n JSON.stringify(pending)\n );\n } catch {\n throw new TeamSignInError(\"storage_blocked\");\n }\n}\n\nfunction returnUrl(): string {\n const url = new URL(window.location.href);\n for (const param of RETURN_PARAMS) {\n url.searchParams.delete(param);\n }\n if (!url.searchParams.has(TEAM_ACTIVATION_PARAM)) {\n url.searchParams.set(TEAM_ACTIVATION_PARAM, \"\");\n }\n return url.href;\n}\n\nasync function exchangeCode(options: {\n apiUrl: string;\n code: string;\n codeVerifier: string;\n}): Promise<TeamAccess> {\n const response = await fetch(\n apiEndpoint(options.apiUrl, \"/api/v1/team/token\"),\n {\n body: JSON.stringify({\n code: options.code,\n codeVerifier: options.codeVerifier,\n }),\n headers: { \"Content-Type\": \"application/json\" },\n method: \"POST\",\n }\n );\n if (!response.ok) {\n const failure = sessionApiErrorSchema.safeParse(\n await response.json().catch(() => null)\n );\n throw new TeamSignInError(\n \"exchange_failed\",\n failure.success ? failure.data.error : undefined\n );\n }\n const access = teamAccessSchema.safeParse(\n await response.json().catch(() => null)\n );\n if (!access.success) {\n throw new TeamSignInError(\"exchange_failed\");\n }\n return access.data;\n}\n\nexport async function prepareTeamSignIn(options: {\n appUrl: string;\n publicKey: string;\n}): Promise<string> {\n const pending = { codeVerifier: randomBase64Url(), state: randomBase64Url() };\n rememberPendingSignIn(options.publicKey, pending);\n const consentUrl = new URL(\"/auth/team\", options.appUrl);\n consentUrl.search = new URLSearchParams({\n code_challenge: await pkceChallengeFor(pending.codeVerifier),\n origin: window.location.origin,\n public_key: options.publicKey,\n return_to: returnUrl(),\n state: pending.state,\n }).toString();\n return consentUrl.href;\n}\n\nexport function hasTeamSignInReturn(): boolean {\n return new URL(window.location.href).searchParams.has(RETURN_STATE_PARAM);\n}\n\nasync function completeReturnedSignIn(options: {\n apiUrl: string;\n code: string | null;\n pending: PendingSignIn | null;\n publicKey: string;\n state: string;\n}): Promise<TeamAccess> {\n if (options.pending?.state !== options.state) {\n throw new TeamSignInError(\"interrupted\");\n }\n if (options.code === null) {\n throw new TeamSignInError(\"cancelled\");\n }\n const access = await exchangeCode({\n apiUrl: options.apiUrl,\n code: options.code,\n codeVerifier: options.pending.codeVerifier,\n });\n persistTeamAccess(options.publicKey, access);\n return access;\n}\n\n/** Strips the returned code from the address bar at once, so it is consumed by one caller only. */\nexport function finishTeamSignIn(options: {\n apiUrl: string;\n publicKey: string;\n}): Promise<TeamAccess> | null {\n const url = new URL(window.location.href);\n const state = url.searchParams.get(RETURN_STATE_PARAM);\n if (state === null) {\n return null;\n }\n const code = url.searchParams.get(RETURN_CODE_PARAM);\n for (const param of RETURN_PARAMS) {\n url.searchParams.delete(param);\n }\n window.history.replaceState(window.history.state, \"\", url.href);\n return completeReturnedSignIn({\n apiUrl: options.apiUrl,\n code,\n pending: takePendingSignIn(options.publicKey),\n publicKey: options.publicKey,\n state,\n });\n}\n\nexport async function forgetTeamAccess(options: {\n apiUrl: string;\n publicKey: string;\n}): Promise<void> {\n const access = storedTeamAccess(options.publicKey);\n persistTeamAccess(options.publicKey, null);\n if (!access) {\n return;\n }\n await fetch(apiEndpoint(options.apiUrl, \"/api/v1/team/revoke\"), {\n headers: { Authorization: `Bearer ${access.token}` },\n method: \"POST\",\n });\n}\n","import { useState } from \"react\";\nimport { failureMessage } from \"../ui/session-workspace\";\n\nexport interface TeamConnection {\n apiUrl: string;\n appUrl: string;\n publicKey: string;\n}\n\nfunction useTeamSignIn(onSignIn: () => Promise<void>) {\n const [isSigningIn, setIsSigningIn] = useState(false);\n const [failure, setFailure] = useState<string | null>(null);\n\n const signIn = async () => {\n setIsSigningIn(true);\n setFailure(null);\n try {\n await onSignIn();\n } catch (error) {\n setFailure(failureMessage(error));\n setIsSigningIn(false);\n }\n };\n\n return { failure, isSigningIn, signIn };\n}\n\nfunction SignInActions({\n canSignIn,\n onHide,\n onSignIn,\n}: {\n canSignIn: boolean;\n onHide: () => void;\n onSignIn: () => void;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={!canSignIn}\n onClick={onSignIn}\n type=\"button\"\n >\n Sign in with Reflet\n </button>\n <button className=\"dt-btn\" onClick={onHide} type=\"button\">\n Hide\n </button>\n </div>\n );\n}\n\nexport function TeamSignInCard({\n isFinishing,\n notice,\n onSignIn,\n continuesInBrowser,\n}: {\n isFinishing: boolean;\n notice: string | null;\n onSignIn: () => Promise<void>;\n continuesInBrowser: boolean;\n}) {\n const [isHidden, setIsHidden] = useState(false);\n const { failure, isSigningIn, signIn } = useTeamSignIn(onSignIn);\n const isWaitingForBrowser = continuesInBrowser && isSigningIn;\n const isLeavingPage = isSigningIn && !continuesInBrowser;\n\n if (isHidden) {\n return null;\n }\n return (\n <section aria-labelledby=\"rf-team-title\" className=\"dt-team-card glass\">\n <h2 className=\"dt-ses-subhead\" id=\"rf-team-title\">\n Reflet team tools\n </h2>\n <p className=\"dt-meta\">\n Sign in with your Reflet account to record a session on this app.\n </p>\n <p className=\"dt-meta\">\n Only members of the app's Reflet organization can sign in.\n </p>\n {isFinishing && (\n <p className=\"dt-meta\" role=\"status\">\n Finishing sign-in…\n </p>\n )}\n {isWaitingForBrowser && (\n <p className=\"dt-meta\" role=\"status\">\n Finish signing in in your browser.\n </p>\n )}\n {notice && (\n <p className=\"dt-meta\" role=\"status\">\n {notice}\n </p>\n )}\n {failure && (\n <p className=\"dt-error\" role=\"alert\">\n {failure}\n </p>\n )}\n <SignInActions\n canSignIn={!(isLeavingPage || isFinishing)}\n onHide={() => setIsHidden(true)}\n onSignIn={signIn}\n />\n </section>\n );\n}\n","import { type ReactNode, useCallback, useState } from \"react\";\nimport { AccountFooter } from \"../../devtools/client/account/account-footer\";\nimport {\n DevtoolsBar,\n DevtoolsBarButtons,\n SessionsBarButton,\n type SheetTab,\n} from \"../../devtools/client/devtools-bar\";\nimport { DevtoolsSheet } from \"../../devtools/client/devtools-sheet\";\nimport { usePageHighlight } from \"../../devtools/client/find-on-page\";\nimport { InboxPanel } from \"../../devtools/client/inbox/inbox-panel\";\nimport { NotePicker } from \"../../devtools/client/notes/note-picker\";\nimport {\n unsentNoteCount,\n useNotes,\n} from \"../../devtools/client/notes/note-store\";\nimport { NotesPanel } from \"../../devtools/client/notes/notes-panel\";\nimport { reportFailure } from \"../../devtools/client/notices\";\nimport { NotePins } from \"../../devtools/client/pins/note-pins\";\nimport type { BoardCall } from \"../../devtools/client/route/dev-route\";\nimport {\n FIRST_SHEET_TAB,\n useSheetTab,\n} from \"../../devtools/client/use-sheet-tab\";\nimport { SelectionOutline } from \"../../feedback/ui/selection-outline\";\nimport type { SessionTransport } from \"../api/session-api\";\nimport { purgeAccount } from \"../local/local-sessions\";\nimport { RecordingLayer } from \"../ui/recording/recording-layer\";\nimport {\n SessionWorkspaceProvider,\n useWorkspaceLoader,\n type WorkspaceState,\n} from \"../ui/session-workspace\";\nimport {\n type SessionNavigation,\n SessionsPanel,\n sessionSheetPlace,\n useSessionNavigation,\n} from \"../ui/sessions-panel\";\n\nconst TEAM_TOOLS_LABEL = \"Reflet team tools\";\nexport const REFUSED_SIGN_IN_COPY =\n \"Reflet no longer accepts this sign-in. Sign in again to record.\";\nconst SESSIONS_TABS: SheetTab[] = [\"sessions\"];\nconst BOARD_TABS: SheetTab[] = [\"inbox\", \"notes\", \"sessions\"];\n\nexport interface TeamPlacement {\n edge: \"bottom\" | \"top\";\n side: \"left\" | \"right\";\n}\n\nexport interface SignedInTeam {\n /** Null where the credential only reaches sessions, like a browser's team token. */\n boardCall: BoardCall | null;\n onSignOut: (reason: string | null) => void;\n organizationName: string;\n transport: SessionTransport;\n}\n\ninterface TeamAccount {\n onSignOut: () => void;\n organizationName: string;\n state: WorkspaceState;\n}\n\nfunction SessionsBody({\n navigation,\n onStarted,\n onWriteNote,\n state,\n}: {\n navigation: SessionNavigation;\n onStarted: () => void;\n onWriteNote?: () => void;\n state: WorkspaceState;\n}) {\n if (state.kind === \"ready\") {\n return (\n <SessionsPanel\n navigation={navigation}\n onStarted={onStarted}\n onWriteNote={onWriteNote}\n />\n );\n }\n if (state.kind === \"failed\") {\n return (\n <div className=\"dt-empty\" role=\"alert\">\n <p>Sessions did not open: {state.message}</p>\n <button className=\"dt-btn\" onClick={state.retry} type=\"button\">\n Try again\n </button>\n </div>\n );\n }\n return <p className=\"dt-status\">Opening your sessions…</p>;\n}\n\nfunction TeamSheet({\n account,\n children,\n navigation,\n onClose,\n onSelectTab,\n side,\n tab,\n tabs,\n}: {\n account: TeamAccount;\n children: ReactNode;\n navigation: SessionNavigation;\n onClose: () => void;\n onSelectTab: (tab: SheetTab) => void;\n side: TeamPlacement[\"side\"];\n tab: SheetTab;\n tabs: SheetTab[];\n}) {\n const { state } = account;\n const place =\n tab === \"sessions\" && state.kind === \"ready\"\n ? sessionSheetPlace(navigation)\n : null;\n return (\n <DevtoolsSheet\n footer={\n place === null && (\n <AccountFooter\n actions={[{ label: \"Sign out\", onSelect: account.onSignOut }]}\n organizationName={account.organizationName}\n person={\n state.kind === \"ready\" ? state.workspace.identity.user : null\n }\n />\n )\n }\n label={TEAM_TOOLS_LABEL}\n navigation={{ onSelectTab, place, tab, tabs }}\n onClose={onClose}\n side={side}\n >\n {children}\n </DevtoolsSheet>\n );\n}\n\nfunction TeamBar({\n children,\n organizationName,\n placement,\n}: {\n children: ReactNode;\n organizationName: string;\n placement: TeamPlacement;\n}) {\n return (\n <DevtoolsBar\n edge={placement.edge}\n label={`${TEAM_TOOLS_LABEL} · ${organizationName}`}\n side={placement.side}\n >\n {children}\n </DevtoolsBar>\n );\n}\n\nfunction useTeamWorkspace(team: SignedInTeam) {\n const { onSignOut } = team;\n const state = useWorkspaceLoader({\n onUnauthorized: () => onSignOut(REFUSED_SIGN_IN_COPY),\n surface: \"app\",\n transport: team.transport,\n });\n const workspace = state.kind === \"ready\" ? state.workspace : null;\n\n const signOut = async () => {\n if (workspace) {\n await purgeAccount(workspace.account.key).catch((error: unknown) =>\n reportFailure(\"This device's session data was not removed\", error)\n );\n }\n onSignOut(null);\n };\n\n const account: TeamAccount = {\n onSignOut: signOut,\n organizationName: team.organizationName,\n state,\n };\n return { account, workspace };\n}\n\nfunction SessionsTeamTools({\n placement,\n team,\n}: {\n placement: TeamPlacement;\n team: SignedInTeam;\n}) {\n const { account, workspace } = useTeamWorkspace(team);\n const [isSheetOpen, setIsSheetOpen] = useState(false);\n const navigation = useSessionNavigation();\n const closeSheet = () => setIsSheetOpen(false);\n\n return (\n <SessionWorkspaceProvider workspace={workspace}>\n {isSheetOpen && (\n <TeamSheet\n account={account}\n navigation={navigation}\n onClose={closeSheet}\n onSelectTab={() => undefined}\n side={placement.side}\n tab=\"sessions\"\n tabs={SESSIONS_TABS}\n >\n <SessionsBody\n navigation={navigation}\n onStarted={closeSheet}\n state={account.state}\n />\n </TeamSheet>\n )}\n <TeamBar organizationName={team.organizationName} placement={placement}>\n <SessionsBarButton onOpen={() => setIsSheetOpen(true)} />\n </TeamBar>\n {workspace && (\n <RecordingLayer\n onFinished={(target) => {\n navigation.go({ target, view: \"review\" });\n setIsSheetOpen(true);\n }}\n />\n )}\n </SessionWorkspaceProvider>\n );\n}\n\n/** The devtools panel minus what needs the source code: no Code tab, no source lookup. */\nfunction BoardTeamTools({\n boardCall,\n placement,\n team,\n}: {\n boardCall: BoardCall;\n placement: TeamPlacement;\n team: SignedInTeam;\n}) {\n const { account, workspace } = useTeamWorkspace(team);\n const sheet = useSheetTab();\n const { openTab } = sheet;\n const navigation = useSessionNavigation();\n const notes = useNotes();\n const { clearHighlight, highlighted, showSelector } = usePageHighlight();\n const [isPicking, setIsPicking] = useState(false);\n const startPick = useCallback(() => setIsPicking(true), []);\n const stopPick = useCallback(() => setIsPicking(false), []);\n\n const closeSheet = () => {\n sheet.close();\n clearHighlight();\n };\n const openPanel = (tab: SheetTab | null) =>\n sheet.select(\n tab ??\n (BOARD_TABS.includes(sheet.lastTab) ? sheet.lastTab : FIRST_SHEET_TAB)\n );\n const writeNoteFromSession = () => {\n closeSheet();\n startPick();\n };\n\n return (\n <SessionWorkspaceProvider workspace={workspace}>\n <div className=\"dt\" data-recessed={isPicking}>\n <NotePins isVisible={!isPicking} notes={notes} />\n {openTab && (\n <TeamSheet\n account={account}\n navigation={navigation}\n onClose={closeSheet}\n onSelectTab={sheet.select}\n side={placement.side}\n tab={openTab}\n tabs={BOARD_TABS}\n >\n {openTab === \"inbox\" && (\n <InboxPanel boardCall={boardCall} onShowSelector={showSelector} />\n )}\n {openTab === \"notes\" && (\n <NotesPanel\n boardCall={boardCall}\n notes={notes}\n onPick={startPick}\n onShowSelector={showSelector}\n sendBlockedReason={null}\n />\n )}\n {openTab === \"sessions\" && (\n <SessionsBody\n navigation={navigation}\n onStarted={closeSheet}\n onWriteNote={writeNoteFromSession}\n state={account.state}\n />\n )}\n </TeamSheet>\n )}\n <TeamBar organizationName={team.organizationName} placement={placement}>\n <DevtoolsBarButtons\n canOpenCode={false}\n onOpen={openPanel}\n onPick={startPick}\n unsentNoteCount={unsentNoteCount(notes)}\n />\n </TeamBar>\n {openTab && <SelectionOutline node={highlighted} />}\n {workspace && (\n <RecordingLayer\n onFinished={(target) => {\n navigation.go({ target, view: \"review\" });\n sheet.select(\"sessions\");\n }}\n />\n )}\n {isPicking && <NotePicker canReadSource={false} onDone={stopPick} />}\n </div>\n </SessionWorkspaceProvider>\n );\n}\n\nexport function TeamTools({\n placement,\n team,\n}: {\n placement: TeamPlacement;\n team: SignedInTeam;\n}) {\n return team.boardCall ? (\n <BoardTeamTools\n boardCall={team.boardCall}\n placement={placement}\n team={team}\n />\n ) : (\n <SessionsTeamTools placement={placement} team={team} />\n );\n}\n","import {\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { DEVTOOLS_STYLES } from \"../../devtools/client/devtools-styles\";\nimport { Notices, reportFailure } from \"../../devtools/client/notices\";\nimport type { BoardCall } from \"../../devtools/client/route/dev-route\";\nimport type { RefletFeedbackProps } from \"../../feedback/types\";\nimport { SessionApiError } from \"../api/session-api\";\nimport {\n bridgeBoardCall,\n bridgeTransport,\n teamTransport,\n} from \"../api/session-transports\";\nimport { failureMessage } from \"../ui/session-workspace\";\nimport { SESSIONS_STYLES } from \"../ui/sessions-styles\";\nimport {\n finishTeamSignIn,\n forgetTeamAccess,\n hasTeamSignInReturn,\n prepareTeamSignIn,\n readTeamAccess,\n} from \"./team-auth\";\nimport { type TeamConnection, TeamSignInCard } from \"./team-sign-in-card\";\nimport {\n REFUSED_SIGN_IN_COPY,\n type TeamPlacement,\n TeamTools,\n} from \"./team-tools\";\nimport type { TeamToolsAccount, TeamToolsBridge } from \"./team-tools-bridge\";\n\nfunction SignedOutAnchor({\n children,\n placement,\n}: {\n children: ReactNode;\n placement: TeamPlacement;\n}) {\n return (\n <div\n className=\"dt-team-anchor\"\n data-edge={placement.edge}\n data-side={placement.side}\n >\n {children}\n </div>\n );\n}\n\n/** A web page signs in by leaving for reflet.app and coming back with a token for its own origin. */\nfunction BrowserTeamAccount({\n connection,\n placement,\n}: {\n connection: TeamConnection;\n placement: TeamPlacement;\n}) {\n const { apiUrl, publicKey } = connection;\n const [access, setAccess] = useState(() => readTeamAccess(publicKey));\n const [notice, setNotice] = useState<string | null>(null);\n const [isFinishing, setIsFinishing] = useState(hasTeamSignInReturn);\n const transport = useMemo(\n () => access && teamTransport({ apiUrl, token: access.token }),\n [access, apiUrl]\n );\n useEffect(() => {\n finishTeamSignIn({ apiUrl, publicKey })\n ?.then(\n (signedIn) => {\n setAccess(signedIn);\n setNotice(null);\n },\n (error: unknown) => setNotice(failureMessage(error))\n )\n .finally(() => setIsFinishing(false));\n }, [apiUrl, publicKey]);\n const signOut = (reason: string | null) => {\n setAccess(null);\n setNotice(reason);\n forgetTeamAccess({ apiUrl, publicKey }).catch((error: unknown) =>\n reportFailure(\"Signing out of Reflet did not finish\", error)\n );\n };\n\n if (access && transport) {\n return (\n <TeamTools\n placement={placement}\n team={{\n boardCall: null,\n onSignOut: signOut,\n organizationName: access.organizationName,\n transport,\n }}\n />\n );\n }\n return (\n <SignedOutAnchor placement={placement}>\n <TeamSignInCard\n continuesInBrowser={false}\n isFinishing={isFinishing}\n notice={notice}\n onSignIn={async () =>\n window.location.assign(await prepareTeamSignIn(connection))\n }\n />\n </SignedOutAnchor>\n );\n}\n\n/** The host already dropped a token Reflet refuses, so later calls would only fail. */\nfunction signsOutWhenRefused(\n boardCall: BoardCall,\n onRefused: () => void\n): BoardCall {\n return async (apiPath, init) => {\n try {\n return await boardCall(apiPath, init);\n } catch (error) {\n if (error instanceof SessionApiError && error.status === 401) {\n onRefused();\n }\n throw error;\n }\n };\n}\n\ntype BridgeAccountState =\n | { kind: \"loading\" }\n | { account: TeamToolsAccount | null; kind: \"loaded\" };\n\n/** A desktop app signs in through the system browser; its privileged process keeps the credential. */\nfunction BridgeTeamAccount({\n bridge,\n placement,\n}: {\n bridge: TeamToolsBridge;\n placement: TeamPlacement;\n}) {\n const [accountState, setAccountState] = useState<BridgeAccountState>({\n kind: \"loading\",\n });\n const [notice, setNotice] = useState<string | null>(null);\n const transport = useMemo(() => bridgeTransport(bridge), [bridge]);\n useEffect(() => {\n let isCurrent = true;\n bridge.account().then(\n (account) => isCurrent && setAccountState({ account, kind: \"loaded\" }),\n (error: unknown) => {\n if (isCurrent) {\n setAccountState({ account: null, kind: \"loaded\" });\n setNotice(failureMessage(error));\n }\n }\n );\n return () => {\n isCurrent = false;\n };\n }, [bridge]);\n const signIn = async () => {\n const account = await bridge.signIn();\n setAccountState({ account, kind: \"loaded\" });\n setNotice(null);\n };\n const signOut = useCallback(\n (reason: string | null) => {\n setAccountState({ account: null, kind: \"loaded\" });\n setNotice(reason);\n bridge\n .signOut()\n .catch((error: unknown) =>\n reportFailure(\"Signing out of Reflet did not finish\", error)\n );\n },\n [bridge]\n );\n const boardCall = useMemo(\n () =>\n signsOutWhenRefused(bridgeBoardCall(bridge), () =>\n signOut(REFUSED_SIGN_IN_COPY)\n ),\n [bridge, signOut]\n );\n\n if (accountState.kind === \"loading\") {\n return null;\n }\n if (accountState.account) {\n return (\n <TeamTools\n placement={placement}\n team={{\n boardCall,\n onSignOut: signOut,\n organizationName: accountState.account.organizationName,\n transport,\n }}\n />\n );\n }\n return (\n <SignedOutAnchor placement={placement}>\n <TeamSignInCard\n continuesInBrowser\n isFinishing={false}\n notice={notice}\n onSignIn={signIn}\n />\n </SignedOutAnchor>\n );\n}\n\nfunction placementFor(\n position: NonNullable<RefletFeedbackProps[\"position\"]>\n): TeamPlacement {\n return {\n edge: position.startsWith(\"top\") ? \"top\" : \"bottom\",\n side: position.endsWith(\"right\") ? \"right\" : \"left\",\n };\n}\n\nexport function TeamLayer(\n props: { position: NonNullable<RefletFeedbackProps[\"position\"]> } & (\n | { bridge: TeamToolsBridge }\n | { connection: TeamConnection }\n )\n) {\n const placement = placementFor(props.position);\n return (\n <div className=\"dt\">\n <style>{`${DEVTOOLS_STYLES}${SESSIONS_STYLES}`}</style>\n {\"bridge\" in props ? (\n <BridgeTeamAccount bridge={props.bridge} placement={placement} />\n ) : (\n <BrowserTeamAccount\n connection={props.connection}\n placement={placement}\n />\n )}\n <Notices />\n </div>\n );\n}\n"],"mappings":"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"}
|