({
token,
name,
type,
size,
version,
workspaceName,
ownerName,
}: PublicFileViewProps)
| 23 | } |
| 24 | |
| 25 | export function PublicFileView({ |
| 26 | token, |
| 27 | name, |
| 28 | type, |
| 29 | size, |
| 30 | version, |
| 31 | workspaceName, |
| 32 | ownerName, |
| 33 | }: PublicFileViewProps) { |
| 34 | const contentUrl = `/api/files/public/${token}/content` |
| 35 | const brand = useBrandConfig() |
| 36 | const provenance = buildProvenance(workspaceName, ownerName) |
| 37 | |
| 38 | // The public viewer reuses the in-app FileViewer; the content source seam swaps |
| 39 | // the auth-gated workspace serve URL for the token-scoped public endpoint, and a |
| 40 | // synthetic record carries the metadata the renderers/query keys need. `key` and |
| 41 | // `updatedAt` fold in the content version so the React Query caches (keyed on the |
| 42 | // storage key + `updatedAt`) refetch when the shared file changes — even when its |
| 43 | // size is unchanged. |
| 44 | // Embedded images route through the token-scoped cascade endpoint, which serves them only when the |
| 45 | // shared document actually references them and they live in its workspace. |
| 46 | const source = useMemo( |
| 47 | () => createPublicFileContentSource(token, contentUrl), |
| 48 | [token, contentUrl] |
| 49 | ) |
| 50 | const file = useMemo<WorkspaceFileRecord>( |
| 51 | () => ({ |
| 52 | id: token, |
| 53 | workspaceId: token, |
| 54 | name, |
| 55 | key: `${token}@${version}`, |
| 56 | path: contentUrl, |
| 57 | size, |
| 58 | type, |
| 59 | uploadedBy: '', |
| 60 | folderId: null, |
| 61 | uploadedAt: new Date(version), |
| 62 | updatedAt: new Date(version), |
| 63 | }), |
| 64 | [token, name, type, size, version, contentUrl] |
| 65 | ) |
| 66 | |
| 67 | return ( |
| 68 | <div className='light flex min-h-screen flex-col bg-[var(--bg)]'> |
| 69 | <header className='sticky top-0 z-10 flex items-center justify-between gap-4 border-[var(--border)] border-b bg-[var(--bg)] px-4 py-3'> |
| 70 | <div className='flex min-w-0 items-center gap-3'> |
| 71 | {!brand.logoUrl && ( |
| 72 | <> |
| 73 | <Link |
| 74 | href='https://sim.ai' |
| 75 | target='_blank' |
| 76 | rel='noopener noreferrer' |
| 77 | aria-label='Sim home' |
| 78 | className='flex shrink-0 items-center' |
| 79 | > |
| 80 | <SimWordmark /> |
| 81 | </Link> |
| 82 | <div className='h-5 w-px shrink-0 bg-[var(--border)]' /> |
nothing calls this directly
no test coverage detected