reflet-sdk 0.7.10 → 0.7.11
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 +6 -0
- package/README.md +6 -5
- package/dist/{devtools-layer-COilp7Ht.js → devtools-layer-Cr-rmnNH.js} +3 -3
- package/dist/{devtools-layer-COilp7Ht.js.map → devtools-layer-Cr-rmnNH.js.map} +1 -1
- package/dist/feedback.js +4 -4
- package/dist/{submit-D7XKlgee.js → submit-C5rEH7AS.js} +2 -2
- package/dist/{submit-D7XKlgee.js.map → submit-C5rEH7AS.js.map} +1 -1
- package/dist/{team-layer-By_81DBU.js → team-layer-CWE2mFbm.js} +3 -3
- package/dist/{team-layer-By_81DBU.js.map → team-layer-CWE2mFbm.js.map} +1 -1
- package/dist/{use-sheet-tab-QLQ1oeso.js → use-sheet-tab-CODfa-67.js} +3 -3
- package/dist/use-sheet-tab-CODfa-67.js.map +1 -0
- package/package.json +1 -1
- package/dist/use-sheet-tab-QLQ1oeso.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { d as SelectionOutline } from "./submit-
|
|
1
|
+
import { d as SelectionOutline } from "./submit-C5rEH7AS.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-
|
|
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";
|
|
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-
|
|
641
|
+
//# sourceMappingURL=team-layer-CWE2mFbm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-layer-By_81DBU.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-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,5 +1,5 @@
|
|
|
1
1
|
import { a as EDITORS, n as DEVTOOLS_REQUEST_HEADER, r as DEVTOOLS_ROUTE_BASE, t as DEVTOOLS_ENDPOINTS } from "./protocol-ClxYWmhu.js";
|
|
2
|
-
import { $ as inspectReactElement, A as PencilIcon, B as DEFAULT_WIDGET_LABELS, C as CheckIcon, D as GripIcon, E as CodeIcon, G as buildElementSelection, H as clip, I as TrashIcon, J as getElementRect, K as buildSelector, N as Svg, P as TargetIcon, Q as getFiberFromNode, T as CloseIcon, U as collectPageContext, V as SDK_VERSION, Y as REDACT_ATTRIBUTE, Z as redactUrl, _ as isSubmitEnter, a as uploadBlob, at as capturedViewportSize, c as useFloatingPosition, d as SelectionOutline, et as resolveComponentStack, h as startsInWidget, it as capturedFromCanvas, k as MoreIcon, l as onViewportChange, m as listenToKeydown, o as ElementPicker, ot as releaseCapture, p as listenOnPageAndWidget, q as describeElement, r as deriveTitle, rt as captureViewport, s as isWidgetOwned, tt as shortenSourcePath, u as visibleViewport, v as matchesHotkey } from "./submit-
|
|
2
|
+
import { $ as inspectReactElement, A as PencilIcon, B as DEFAULT_WIDGET_LABELS, C as CheckIcon, D as GripIcon, E as CodeIcon, G as buildElementSelection, H as clip, I as TrashIcon, J as getElementRect, K as buildSelector, N as Svg, P as TargetIcon, Q as getFiberFromNode, T as CloseIcon, U as collectPageContext, V as SDK_VERSION, Y as REDACT_ATTRIBUTE, Z as redactUrl, _ as isSubmitEnter, a as uploadBlob, at as capturedViewportSize, c as useFloatingPosition, d as SelectionOutline, et as resolveComponentStack, h as startsInWidget, it as capturedFromCanvas, k as MoreIcon, l as onViewportChange, m as listenToKeydown, o as ElementPicker, ot as releaseCapture, p as listenOnPageAndWidget, q as describeElement, r as deriveTitle, rt as captureViewport, s as isWidgetOwned, tt as shortenSourcePath, u as visibleViewport, v as matchesHotkey } from "./submit-C5rEH7AS.js";
|
|
3
3
|
import { t as REFLET_Z_INDEX } from "./z-index-CwokqVq_.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import * as G$1 from "react";
|
|
@@ -6807,7 +6807,7 @@ function DisclosureList() {
|
|
|
6807
6807
|
}), /* @__PURE__ */ jsxs("ul", {
|
|
6808
6808
|
className: "dt-ses-list",
|
|
6809
6809
|
children: [
|
|
6810
|
-
/* @__PURE__ */ jsx("li", { children: "Your voice while recording. It is sent to Reflet and transcribed by
|
|
6810
|
+
/* @__PURE__ */ jsx("li", { children: "Your voice while recording. It is sent to Reflet and transcribed by ElevenLabs Scribe through OpenRouter with zero data retention. The audio is deleted as soon as its transcript is saved, within 24 hours at most." }),
|
|
6811
6811
|
/* @__PURE__ */ jsx("li", { children: "The page: its address without sensitive parameters, its title, the scroll position and the window size." }),
|
|
6812
6812
|
/* @__PURE__ */ jsx("li", { children: "What you click, point at and mark: element names and positions, never your keystrokes." }),
|
|
6813
6813
|
/* @__PURE__ */ jsxs("li", { children: [
|
|
@@ -13595,4 +13595,4 @@ function useSheetTab() {
|
|
|
13595
13595
|
//#endregion
|
|
13596
13596
|
export { sessionSheetPlace as A, teamTransport as B, AccountFooter as C, MissingRouteHint as D, MISSING_SECRET_KEY_HINT as E, useWorkspaceLoader as F, SessionApiError as G, disconnectBoard as H, purgeAccount as I, reportFailure as J, sessionApiErrorSchema as K, bridgeBoardCall as L, RecordingLayer as M, SessionWorkspaceProvider as N, SESSIONS_STYLES as O, failureMessage as P, bridgeTransport as R, InboxPanel as S, CONNECT_REQUIREMENT as T, probeDevRoute as U, callReflet as V, startBoardConnect as W, DevtoolsBarButtons as _, NotePicker as a, CodeTab as b, isActiveNote as c, useNotes as d, findOnPage as f, DevtoolsBar as g, DevtoolsSheet as h, NotesPanel as i, useSessionNavigation as j, SessionsPanel as k, isNoteOnPage as l, DEVTOOLS_STYLES as m, useSheetTab as n, enrichNote as o, usePageHighlight as p, Notices as q, NotePins as r, hasTriedToLocate as s, FIRST_SHEET_TAB as t, unsentNoteCount as u, SHEET_TABS as v, AccountNote as w, useCodeLookup as x, SessionsBarButton as y, devtoolsTransport as z };
|
|
13597
13597
|
|
|
13598
|
-
//# sourceMappingURL=use-sheet-tab-
|
|
13598
|
+
//# sourceMappingURL=use-sheet-tab-CODfa-67.js.map
|