| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | import type { FC } from 'react'import { useState } from 'react'import { useTranslation } from 'react-i18next'import Uploader from './uploader'import ImageLinkInput from './image-link-input'import cn from '@/utils/classnames'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}>      {hovering => (        <div          className={`            relative flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer            ${hovering && 'bg-gray-100'}          `}        >          <ImagePlus className="w-4 h-4 text-gray-500" />        </div>      )}    </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)  const hasUploadFromLocal = methods.find(    method => method === TransferMethod.local_file,  )  const handleUpload = (imageFile: ImageFile) => {    onUpload(imageFile)  }  const closePopover = () => setOpen(false)  const handleToggle = () => {    if (disabled)      return    setOpen(v => !v)  }  return (    <PortalToFollowElem      open={open}      onOpenChange={setOpen}      placement="top-start"    >      <PortalToFollowElemTrigger onClick={handleToggle}>        <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>      </PortalToFollowElemTrigger>      <PortalToFollowElemContent className="z-50">        <div className="p-2 w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg">          <ImageLinkInput onUpload={handleUpload} disabled={disabled} />          {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>            </>          )}        </div>      </PortalToFollowElemContent>    </PortalToFollowElem>  )}type ChatImageUploaderProps = {  settings: VisionSettings  onUpload: (imageFile: ImageFile) => void  disabled?: boolean}const ChatImageUploader: FC<ChatImageUploaderProps> = ({  settings,  onUpload,  disabled,}) => {  const onlyUploadLocal    = settings.transfer_methods.length === 1    && settings.transfer_methods[0] === TransferMethod.local_file  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
 |