| import { useCallback, useState } from 'react'; | |
| import { useToastContext } from '@librechat/client'; | |
| import type { SharePointFile, SharePointBatchProgress } from '~/data-provider/Files'; | |
| import { useSharePointBatchDownload } from '~/data-provider/Files'; | |
| import useSharePointToken from './useSharePointToken'; | |
| interface UseSharePointDownloadProps { | |
| onFilesDownloaded?: (files: File[]) => void | Promise<void>; | |
| onError?: (error: Error) => void; | |
| } | |
| interface UseSharePointDownloadReturn { | |
| downloadSharePointFiles: (files: SharePointFile[]) => Promise<File[]>; | |
| isDownloading: boolean; | |
| downloadProgress: SharePointBatchProgress | null; | |
| error: string | null; | |
| } | |
| export default function useSharePointDownload({ | |
| onFilesDownloaded, | |
| onError, | |
| }: UseSharePointDownloadProps = {}): UseSharePointDownloadReturn { | |
| const { showToast } = useToastContext(); | |
| const [downloadProgress, setDownloadProgress] = useState<SharePointBatchProgress | null>(null); | |
| const [error, setError] = useState<string | null>(null); | |
| const { token, refetch: refetchToken } = useSharePointToken({ | |
| enabled: false, | |
| purpose: 'Download', | |
| }); | |
| const batchDownloadMutation = useSharePointBatchDownload(); | |
| const downloadSharePointFiles = useCallback( | |
| async (files: SharePointFile[]): Promise<File[]> => { | |
| if (!files || files.length === 0) { | |
| throw new Error('No files provided for download'); | |
| } | |
| setError(null); | |
| setDownloadProgress({ completed: 0, total: files.length, failed: [] }); | |
| try { | |
| let accessToken = token?.access_token; | |
| if (!accessToken) { | |
| showToast({ | |
| message: 'Getting SharePoint access token...', | |
| status: 'info', | |
| duration: 2000, | |
| }); | |
| const tokenResult = await refetchToken(); | |
| accessToken = tokenResult.data?.access_token; | |
| if (!accessToken) { | |
| throw new Error('Failed to obtain SharePoint access token'); | |
| } | |
| } | |
| showToast({ | |
| message: `Downloading ${files.length} file(s) from SharePoint...`, | |
| status: 'info', | |
| duration: 3000, | |
| }); | |
| const downloadedFiles = await batchDownloadMutation.mutateAsync({ | |
| files, | |
| accessToken, | |
| onProgress: (progress) => { | |
| setDownloadProgress(progress); | |
| if (files.length > 5 && progress.completed % 3 === 0) { | |
| showToast({ | |
| message: `Downloaded ${progress.completed}/${progress.total} files...`, | |
| status: 'info', | |
| duration: 1000, | |
| }); | |
| } | |
| }, | |
| }); | |
| if (downloadedFiles.length > 0) { | |
| const failedCount = files.length - downloadedFiles.length; | |
| const successMessage = | |
| failedCount > 0 | |
| ? `Downloaded ${downloadedFiles.length}/${files.length} files from SharePoint (${failedCount} failed)` | |
| : `Successfully downloaded ${downloadedFiles.length} file(s) from SharePoint`; | |
| showToast({ | |
| message: successMessage, | |
| status: failedCount > 0 ? 'warning' : 'success', | |
| duration: 4000, | |
| }); | |
| if (onFilesDownloaded) { | |
| await onFilesDownloaded(downloadedFiles); | |
| } | |
| } | |
| setDownloadProgress(null); | |
| return downloadedFiles; | |
| } catch (error) { | |
| const errorMessage = error instanceof Error ? error.message : 'Unknown download error'; | |
| setError(errorMessage); | |
| showToast({ | |
| message: `SharePoint download failed: ${errorMessage}`, | |
| status: 'error', | |
| duration: 5000, | |
| }); | |
| if (onError) { | |
| onError(error instanceof Error ? error : new Error(errorMessage)); | |
| } | |
| setDownloadProgress(null); | |
| throw error; | |
| } | |
| }, | |
| [token, showToast, batchDownloadMutation, onFilesDownloaded, onError, refetchToken], | |
| ); | |
| return { | |
| downloadSharePointFiles, | |
| isDownloading: batchDownloadMutation.isLoading, | |
| downloadProgress, | |
| error, | |
| }; | |
| } | |