import React, {useCallback, useMemo, useState} from 'react'; import type { SuperagentMediaPicker, } from '../../types'; import {AttachmentPickerStatusModal} from './AttachmentPickerStatusModal'; import { getAttachmentPickerErrorMessage, pickAndUploadAttachments, } from './attachmentUpload'; export type SuperagentAttachmentPickerMode = 'camera' | 'files' | 'photos'; export type SuperagentNativeMediaItem = { mimeType?: string; name?: string; previewUri?: string; size?: number; thumbnailUri?: string; type?: string; uploadUri?: string; uri?: string; }; export type SuperagentAttachmentPickerAdapters = { isCancel?: (error: unknown) => boolean; pickNativeMedia: (mode: SuperagentAttachmentPickerMode) => Promise; }; type PickerStatus = { isError?: boolean; message: string; title: string; }; type UseSuperagentAttachmentPickerInput = { baseUrl: string; getAccessToken: () => Promise | string | null | undefined; nativeAdapters: SuperagentAttachmentPickerAdapters; }; export function useSuperagentAttachmentPicker(input?: UseSuperagentAttachmentPickerInput) { const [pickerStatus, setPickerStatus] = useState(null); // No input (host wired no attachment adapters) → the composer's file/photo/camera // affordances stay hidden, so each picker is `undefined` rather than a no-op. const createPicker = useCallback((mode: SuperagentAttachmentPickerMode): SuperagentMediaPicker | undefined => { if (!input) { return undefined; } const { baseUrl, getAccessToken, nativeAdapters } = input; return async (context) => { const authToken = await getAccessToken(); if (!authToken) { setPickerStatus({ isError: true, message: 'Sign in again before attaching files.', title: 'Attachment unavailable', }); return null; } try { const attachments = await pickAndUploadAttachments({ authToken, baseUrl, context, mode, nativeAdapters, onUploadStart: (count) => { setPickerStatus({ message: `Uploading ${count === 1 ? 'attachment' : `${count} attachments`}...`, title: 'Attaching files', }); }, }); if (!attachments.length) { return null; } setPickerStatus(null); return attachments; } catch (error) { if (nativeAdapters.isCancel?.(error)) { setPickerStatus(null); return null; } setPickerStatus({ isError: true, message: getAttachmentPickerErrorMessage(error), title: 'Attachment failed', }); return null; } }; }, [input]); const attachmentPickerModal = useMemo(() => { if (!pickerStatus) { return null; } return ( setPickerStatus(null)} title={pickerStatus.title} /> ); }, [pickerStatus]); return { attachmentPickerModal, onPickFiles: createPicker('files'), onPickPhotos: createPicker('photos'), onTakePhoto: createPicker('camera'), }; }