legends810/testingnew
0
1import React, { useState } from 'react';2import type { Message } from 'ai';3import { toast } from 'react-toastify';4import { MAX_FILES, isBinaryFile, shouldIncludeFile } from '~/utils/fileUtils';5import { createChatFromFolder } from '~/utils/folderImport';6import { logStore } from '~/lib/stores/logs'; // Assuming logStore is imported from this location7import { Button } from '~/components/ui/Button';8import { classNames } from '~/utils/classNames';9 10interface ImportFolderButtonProps {11 className?: string;12 importChat?: (description: string, messages: Message[]) => Promise<void>;13}14 15export const ImportFolderButton: React.FC<ImportFolderButtonProps> = ({ className, importChat }) => {16 const [isLoading, setIsLoading] = useState(false);17 18 const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {19 const allFiles = Array.from(e.target.files || []);20 21 const filteredFiles = allFiles.filter((file) => {22 const path = file.webkitRelativePath.split('/').slice(1).join('/');23 const include = shouldIncludeFile(path);24 25 return include;26 });27 28 if (filteredFiles.length === 0) {29 const error = new Error('No valid files found');30 logStore.logError('File import failed - no valid files', error, { folderName: 'Unknown Folder' });31 toast.error('No files found in the selected folder');32 33 return;34 }35 36 if (filteredFiles.length > MAX_FILES) {37 const error = new Error(`Too many files: ${filteredFiles.length}`);38 logStore.logError('File import failed - too many files', error, {39 fileCount: filteredFiles.length,40 maxFiles: MAX_FILES,41 });42 toast.error(43 `This folder contains ${filteredFiles.length.toLocaleString()} files. This product is not yet optimized for very large projects. Please select a folder with fewer than ${MAX_FILES.toLocaleString()} files.`,44 );45 46 return;47 }48 49 const folderName = filteredFiles[0]?.webkitRelativePath.split('/')[0] || 'Unknown Folder';50 setIsLoading(true);51 52 const loadingToast = toast.loading(`Importing ${folderName}...`);53 54 try {55 const fileChecks = await Promise.all(56 filteredFiles.map(async (file) => ({57 file,58 isBinary: await isBinaryFile(file),59 })),60 );61 62 const textFiles = fileChecks.filter((f) => !f.isBinary).map((f) => f.file);63 const binaryFilePaths = fileChecks64 .filter((f) => f.isBinary)65 .map((f) => f.file.webkitRelativePath.split('/').slice(1).join('/'));66 67 if (textFiles.length === 0) {68 const error = new Error('No text files found');69 logStore.logError('File import failed - no text files', error, { folderName });70 toast.error('No text files found in the selected folder');71 72 return;73 }74 75 if (binaryFilePaths.length > 0) {76 logStore.logWarning(`Skipping binary files during import`, {77 folderName,78 binaryCount: binaryFilePaths.length,79 });80 toast.info(`Skipping ${binaryFilePaths.length} binary files`);81 }82 83 const messages = await createChatFromFolder(textFiles, binaryFilePaths, folderName);84 85 if (importChat) {86 await importChat(folderName, [...messages]);87 }88 89 logStore.logSystem('Folder imported successfully', {90 folderName,91 textFileCount: textFiles.length,92 binaryFileCount: binaryFilePaths.length,93 });94 toast.success('Folder imported successfully');95 } catch (error) {96 logStore.logError('Failed to import folder', error, { folderName });97 console.error('Failed to import folder:', error);98 toast.error('Failed to import folder');99 } finally {100 setIsLoading(false);101 toast.dismiss(loadingToast);102 e.target.value = ''; // Reset file input103 }104 };105 106 return (107 <>108 <input109 type="file"110 id="folder-import"111 className="hidden"112 webkitdirectory=""113 directory=""114 onChange={handleFileChange}115 {...({} as any)}116 />117 <Button118 onClick={() => {119 const input = document.getElementById('folder-import');120 input?.click();121 }}122 title="Import Folder"123 variant="outline"124 size="lg"125 className={classNames(126 'gap-2 bg-[#F5F5F5] dark:bg-[#252525]',127 'text-bolt-elements-textPrimary dark:text-white',128 'hover:bg-[#E5E5E5] dark:hover:bg-[#333333]',129 'border-[#E5E5E5] dark:border-[#333333]',130 'h-10 px-4 py-2 min-w-[120px] justify-center',131 'transition-all duration-200 ease-in-out',132 className,133 )}134 disabled={isLoading}135 >136 <span className="i-ph:upload-simple w-4 h-4" />137 {isLoading ? 'Importing...' : 'Import Folder'}138 </Button>139 </>140 );141};142 