import { useState, useEffect } from 'react'; import { Spin } from 'antd'; import type { CSSProperties } from 'react'; import { getAccessToken } from '../auth/oidc'; export function useAuthUrl(url: string | null | undefined): string | null { const [blobUrl, setBlobUrl] = useState(null); useEffect(() => { if (!url) { setBlobUrl(null); return; } let cancelled = false; let objectUrl: string | undefined; (async () => { try { const token = await getAccessToken(); if (cancelled) return; const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }); if (cancelled || !res.ok) return; const blob = await res.blob(); if (cancelled) return; objectUrl = URL.createObjectURL(blob); setBlobUrl(objectUrl); } catch { // image/resource just won't show } })(); return () => { cancelled = true; setBlobUrl(null); if (objectUrl) URL.revokeObjectURL(objectUrl); }; }, [url]); return blobUrl; } interface AuthImageProps { src: string; width?: number | string; height?: number | string; style?: CSSProperties; alt?: string; } export function AuthImage({ src, width, height, style, alt = '' }: AuthImageProps) { const blobUrl = useAuthUrl(src); if (!blobUrl) { return (
); } return {alt}; } interface AuthIframeProps { src: string; style?: CSSProperties; title?: string; } export function AuthIframe({ src, style, title }: AuthIframeProps) { const hashIdx = src.indexOf('#'); const cleanUrl = hashIdx >= 0 ? src.slice(0, hashIdx) : src; const hash = hashIdx >= 0 ? src.slice(hashIdx) : ''; const blobUrl = useAuthUrl(cleanUrl); if (!blobUrl) { return (
); } return