| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  | import type { FC } from 'react' | 
					
						
							|  |  |  | import { useState } from 'react' | 
					
						
							|  |  |  | import { useTranslation } from 'react-i18next' | 
					
						
							|  |  |  | import Uploader from './uploader' | 
					
						
							|  |  |  | import ImageLinkInput from './image-link-input' | 
					
						
							| 
									
										
										
										
											2024-07-09 15:05:40 +08:00
										 |  |  | import cn from '@/utils/classnames' | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  | import { ImagePlus } from '@/app/components/base/icons/src/vender/line/images' | 
					
						
							|  |  |  | import { TransferMethod } from '@/types/app' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   PortalToFollowElem, | 
					
						
							|  |  |  |   PortalToFollowElemContent, | 
					
						
							|  |  |  |   PortalToFollowElemTrigger, | 
					
						
							|  |  |  | } from '@/app/components/base/portal-to-follow-elem' | 
					
						
							|  |  |  | import { Upload03 } from '@/app/components/base/icons/src/vender/line/general' | 
					
						
							|  |  |  | import type { ImageFile, VisionSettings } from '@/types/app' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type UploadOnlyFromLocalProps = { | 
					
						
							|  |  |  |   onUpload: (imageFile: ImageFile) => void | 
					
						
							|  |  |  |   disabled?: boolean | 
					
						
							|  |  |  |   limit?: number | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | const UploadOnlyFromLocal: FC<UploadOnlyFromLocalProps> = ({ | 
					
						
							|  |  |  |   onUpload, | 
					
						
							|  |  |  |   disabled, | 
					
						
							|  |  |  |   limit, | 
					
						
							|  |  |  | }) => { | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <Uploader onUpload={onUpload} disabled={disabled} limit={limit}> | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |       {hovering => ( | 
					
						
							|  |  |  |         <div | 
					
						
							|  |  |  |           className={`
 | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |             relative flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer | 
					
						
							|  |  |  |             ${hovering && 'bg-gray-100'} | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |           `}
 | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <ImagePlus className="w-4 h-4 text-gray-500" /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       )} | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |     </Uploader> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type UploaderButtonProps = { | 
					
						
							|  |  |  |   methods: VisionSettings['transfer_methods'] | 
					
						
							|  |  |  |   onUpload: (imageFile: ImageFile) => void | 
					
						
							|  |  |  |   disabled?: boolean | 
					
						
							|  |  |  |   limit?: number | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | const UploaderButton: FC<UploaderButtonProps> = ({ | 
					
						
							|  |  |  |   methods, | 
					
						
							|  |  |  |   onUpload, | 
					
						
							|  |  |  |   disabled, | 
					
						
							|  |  |  |   limit, | 
					
						
							|  |  |  | }) => { | 
					
						
							|  |  |  |   const { t } = useTranslation() | 
					
						
							|  |  |  |   const [open, setOpen] = useState(false) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |   const hasUploadFromLocal = methods.find( | 
					
						
							|  |  |  |     method => method === TransferMethod.local_file, | 
					
						
							|  |  |  |   ) | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleUpload = (imageFile: ImageFile) => { | 
					
						
							|  |  |  |     onUpload(imageFile) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |   const closePopover = () => setOpen(false) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |   const handleToggle = () => { | 
					
						
							|  |  |  |     if (disabled) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setOpen(v => !v) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <PortalToFollowElem | 
					
						
							|  |  |  |       open={open} | 
					
						
							|  |  |  |       onOpenChange={setOpen} | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |       placement="top-start" | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |     > | 
					
						
							|  |  |  |       <PortalToFollowElemTrigger onClick={handleToggle}> | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |         <button | 
					
						
							|  |  |  |           type="button" | 
					
						
							|  |  |  |           disabled={disabled} | 
					
						
							|  |  |  |           className="relative flex items-center justify-center w-8 h-8 enabled:hover:bg-gray-100 rounded-lg disabled:cursor-not-allowed" | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <ImagePlus className="w-4 h-4 text-gray-500" /> | 
					
						
							|  |  |  |         </button> | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |       </PortalToFollowElemTrigger> | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |       <PortalToFollowElemContent className="z-50"> | 
					
						
							|  |  |  |         <div className="p-2 w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg"> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |           <ImageLinkInput onUpload={handleUpload} disabled={disabled} /> | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |           {hasUploadFromLocal && ( | 
					
						
							|  |  |  |             <> | 
					
						
							|  |  |  |               <div className="flex items-center mt-2 px-2 text-xs font-medium text-gray-400"> | 
					
						
							|  |  |  |                 <div className="mr-3 w-[93px] h-[1px] bg-gradient-to-l from-[#F3F4F6]" /> | 
					
						
							|  |  |  |                 OR | 
					
						
							|  |  |  |                 <div className="ml-3 w-[93px] h-[1px] bg-gradient-to-r from-[#F3F4F6]" /> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |               <Uploader | 
					
						
							|  |  |  |                 onUpload={handleUpload} | 
					
						
							|  |  |  |                 limit={limit} | 
					
						
							|  |  |  |                 closePopover={closePopover} | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 {hovering => ( | 
					
						
							|  |  |  |                   <div | 
					
						
							|  |  |  |                     className={cn( | 
					
						
							|  |  |  |                       'flex items-center justify-center h-8 text-[13px] font-medium text-[#155EEF] rounded-lg cursor-pointer', | 
					
						
							|  |  |  |                       hovering && 'bg-primary-50', | 
					
						
							|  |  |  |                     )} | 
					
						
							|  |  |  |                   > | 
					
						
							|  |  |  |                     <Upload03 className="mr-1 w-4 h-4" /> | 
					
						
							|  |  |  |                     {t('common.imageUploader.uploadFromComputer')} | 
					
						
							|  |  |  |                   </div> | 
					
						
							|  |  |  |                 )} | 
					
						
							|  |  |  |               </Uploader> | 
					
						
							|  |  |  |             </> | 
					
						
							|  |  |  |           )} | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |         </div> | 
					
						
							|  |  |  |       </PortalToFollowElemContent> | 
					
						
							|  |  |  |     </PortalToFollowElem> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ChatImageUploaderProps = { | 
					
						
							|  |  |  |   settings: VisionSettings | 
					
						
							|  |  |  |   onUpload: (imageFile: ImageFile) => void | 
					
						
							|  |  |  |   disabled?: boolean | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | const ChatImageUploader: FC<ChatImageUploaderProps> = ({ | 
					
						
							|  |  |  |   settings, | 
					
						
							|  |  |  |   onUpload, | 
					
						
							|  |  |  |   disabled, | 
					
						
							|  |  |  | }) => { | 
					
						
							| 
									
										
										
										
											2024-03-10 13:11:41 +08:00
										 |  |  |   const onlyUploadLocal | 
					
						
							|  |  |  |     = settings.transfer_methods.length === 1 | 
					
						
							|  |  |  |     && settings.transfer_methods[0] === TransferMethod.local_file | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (onlyUploadLocal) { | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |       <UploadOnlyFromLocal | 
					
						
							|  |  |  |         onUpload={onUpload} | 
					
						
							|  |  |  |         disabled={disabled} | 
					
						
							|  |  |  |         limit={+settings.image_file_size_limit!} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <UploaderButton | 
					
						
							|  |  |  |       methods={settings.transfer_methods} | 
					
						
							|  |  |  |       onUpload={onUpload} | 
					
						
							|  |  |  |       disabled={disabled} | 
					
						
							|  |  |  |       limit={+settings.image_file_size_limit!} | 
					
						
							|  |  |  |     /> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default ChatImageUploader |