reflet-sdk 0.7.6 → 0.7.7

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +13 -5
  3. package/dist/desktop.d.ts.map +1 -1
  4. package/dist/desktop.js +3 -2
  5. package/dist/desktop.js.map +1 -1
  6. package/dist/devtools-layer-CYIoe3Vo.js +372 -0
  7. package/dist/devtools-layer-CYIoe3Vo.js.map +1 -0
  8. package/dist/devtools-next.js +1 -1
  9. package/dist/devtools-vite.js +3 -3
  10. package/dist/feedback.js +4 -5
  11. package/dist/feedback.js.map +1 -1
  12. package/dist/{handler-ndF3gZBx.js → handler-1XhfZvZ0.js} +3 -3
  13. package/dist/{handler-ndF3gZBx.js.map → handler-1XhfZvZ0.js.map} +1 -1
  14. package/dist/{protocol-cJVVwnPe.js → protocol-BnurX0CF.js} +2 -1
  15. package/dist/protocol-BnurX0CF.js.map +1 -0
  16. package/dist/{reflet-proxy-BW6q9xds.js → reflet-proxy-DVE6ov2f.js} +14 -7
  17. package/dist/reflet-proxy-DVE6ov2f.js.map +1 -0
  18. package/dist/{submit-DsJwTy3X.js → submit-r3_M1ITo.js} +49 -3
  19. package/dist/submit-r3_M1ITo.js.map +1 -0
  20. package/dist/{team-layer-VlQtvR5O.js → team-layer-5-uPYTjV.js} +162 -33
  21. package/dist/team-layer-5-uPYTjV.js.map +1 -0
  22. package/dist/{devtools-styles-DQpiubGB.js → use-sheet-tab-CacYFVjI.js} +4232 -673
  23. package/dist/use-sheet-tab-CacYFVjI.js.map +1 -0
  24. package/package.json +1 -1
  25. package/dist/devtools-layer-xN47FKpW.js +0 -3818
  26. package/dist/devtools-layer-xN47FKpW.js.map +0 -1
  27. package/dist/devtools-styles-DQpiubGB.js.map +0 -1
  28. package/dist/protocol-cJVVwnPe.js.map +0 -1
  29. package/dist/reflet-proxy-BW6q9xds.js.map +0 -1
  30. package/dist/selection-outline-NzAAAZXR.js +0 -51
  31. package/dist/selection-outline-NzAAAZXR.js.map +0 -1
  32. package/dist/submit-DsJwTy3X.js.map +0 -1
  33. package/dist/team-layer-VlQtvR5O.js.map +0 -1
@@ -1,7 +1,8 @@
1
+ import { d as SelectionOutline } from "./submit-r3_M1ITo.js";
1
2
  import { r as teamAccessStorageKey, t as TEAM_ACTIVATION_PARAM } from "./team-activation-Cv5U7OF1.js";
2
- import { B as reportFailure, C as bridgeTransport, L as sessionApiErrorSchema, R as Notices, S as purgeAccount, T as teamTransport, _ as RecordingLayer, b as failureMessage, d as sessionSheetPlace, f as useSessionNavigation, l as SESSIONS_STYLES, n as DevtoolsSheet, o as SessionsBarButton, r as DevtoolsBar, s as AccountFooter, t as DEVTOOLS_STYLES, u as SessionsPanel, x as useWorkspaceLoader, y as SessionWorkspaceProvider } from "./devtools-styles-DQpiubGB.js";
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-CacYFVjI.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-layer.tsx
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
- function SessionsBody({ navigation, onStarted, state }) {
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: () => void 0,
318
+ onSelectTab,
311
319
  place,
312
- tab: "sessions",
313
- tabs: ["sessions"]
320
+ tab,
321
+ tabs
314
322
  },
315
323
  onClose,
316
324
  side,
317
- children: /* @__PURE__ */ jsx(SessionsBody, {
318
- navigation,
319
- onStarted: onClose,
320
- state
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
- signOut,
338
- state,
349
+ account: {
350
+ onSignOut: signOut,
351
+ organizationName: team.organizationName,
352
+ state
353
+ },
339
354
  workspace
340
355
  };
341
356
  }
342
- function TeamTools({ team, placement }) {
343
- const { signOut, state, workspace } = useTeamWorkspace(team);
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: () => setIsSheetOpen(false),
357
- side: placement.side
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-VlQtvR5O.js.map
641
+ //# sourceMappingURL=team-layer-5-uPYTjV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-layer-5-uPYTjV.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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"}