reflet-sdk 0.7.11 → 0.7.12

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.
@@ -1,6 +1,6 @@
1
- import { d as SelectionOutline } from "./submit-C5rEH7AS.js";
1
+ import { d as SelectionOutline } from "./submit-CqeMuBPt.js";
2
2
  import { r as teamAccessStorageKey, t as TEAM_ACTIVATION_PARAM } from "./team-activation-Cv5U7OF1.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-CODfa-67.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-DTGgQ_1c.js";
4
4
  import { z } from "zod";
5
5
  import { useCallback, useEffect, useMemo, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -638,4 +638,4 @@ function TeamLayer(props) {
638
638
  //#endregion
639
639
  export { TeamLayer };
640
640
 
641
- //# sourceMappingURL=team-layer-CWE2mFbm.js.map
641
+ //# sourceMappingURL=team-layer-BdytvHiG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"team-layer-CWE2mFbm.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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"}
1
+ {"version":3,"file":"team-layer-BdytvHiG.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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"}