| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 | 
							- import type { FC } from 'react'
 - import { useCallback, useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import type { Area } from 'react-easy-crop'
 - import Modal from '../modal'
 - import Divider from '../divider'
 - import Button from '../button'
 - import { ImagePlus } from '../icons/src/vender/line/images'
 - import { useLocalFileUploader } from '../image-uploader/hooks'
 - import EmojiPickerInner from '../emoji-picker/Inner'
 - import Uploader from './Uploader'
 - import s from './style.module.css'
 - import getCroppedImg from './utils'
 - import type { AppIconType, ImageFile } from '@/types/app'
 - import cn from '@/utils/classnames'
 - import { DISABLE_UPLOAD_IMAGE_AS_ICON } from '@/config'
 - export type AppIconEmojiSelection = {
 -   type: 'emoji'
 -   icon: string
 -   background: string
 - }
 - 
 - export type AppIconImageSelection = {
 -   type: 'image'
 -   fileId: string
 -   url: string
 - }
 - 
 - export type AppIconSelection = AppIconEmojiSelection | AppIconImageSelection
 - 
 - type AppIconPickerProps = {
 -   onSelect?: (payload: AppIconSelection) => void
 -   onClose?: () => void
 -   className?: string
 - }
 - 
 - const AppIconPicker: FC<AppIconPickerProps> = ({
 -   onSelect,
 -   onClose,
 -   className,
 - }) => {
 -   const { t } = useTranslation()
 - 
 -   const tabs = [
 -     { key: 'emoji', label: t('app.iconPicker.emoji'), icon: <span className="text-lg">🤖</span> },
 -     { key: 'image', label: t('app.iconPicker.image'), icon: <ImagePlus /> },
 -   ]
 -   const [activeTab, setActiveTab] = useState<AppIconType>('emoji')
 - 
 -   const [emoji, setEmoji] = useState<{ emoji: string; background: string }>()
 -   const handleSelectEmoji = useCallback((emoji: string, background: string) => {
 -     setEmoji({ emoji, background })
 -   }, [setEmoji])
 - 
 -   const [uploading, setUploading] = useState<boolean>()
 - 
 -   const { handleLocalFileUpload } = useLocalFileUploader({
 -     limit: 3,
 -     disabled: false,
 -     onUpload: (imageFile: ImageFile) => {
 -       if (imageFile.fileId) {
 -         setUploading(false)
 -         onSelect?.({
 -           type: 'image',
 -           fileId: imageFile.fileId,
 -           url: imageFile.url,
 -         })
 -       }
 -     },
 -   })
 - 
 -   const [imageCropInfo, setImageCropInfo] = useState<{ tempUrl: string; croppedAreaPixels: Area; fileName: string }>()
 -   const handleImageCropped = async (tempUrl: string, croppedAreaPixels: Area, fileName: string) => {
 -     setImageCropInfo({ tempUrl, croppedAreaPixels, fileName })
 -   }
 - 
 -   const handleSelect = async () => {
 -     if (activeTab === 'emoji') {
 -       if (emoji) {
 -         onSelect?.({
 -           type: 'emoji',
 -           icon: emoji.emoji,
 -           background: emoji.background,
 -         })
 -       }
 -     }
 -     else {
 -       if (!imageCropInfo)
 -         return
 -       setUploading(true)
 -       const blob = await getCroppedImg(imageCropInfo.tempUrl, imageCropInfo.croppedAreaPixels, imageCropInfo.fileName)
 -       const file = new File([blob], imageCropInfo.fileName, { type: blob.type })
 -       handleLocalFileUpload(file)
 -     }
 -   }
 - 
 -   return <Modal
 -     onClose={() => { }}
 -     isShow
 -     closable={false}
 -     wrapperClassName={className}
 -     className={cn(s.container, '!w-[362px] !p-0')}
 -   >
 -     {!DISABLE_UPLOAD_IMAGE_AS_ICON && <div className="p-2 pb-0 w-full">
 -       <div className='p-1 flex items-center justify-center gap-2 bg-background-body rounded-xl'>
 -         {tabs.map(tab => (
 -           <button
 -             key={tab.key}
 -             className={`
 -                         p-2 flex-1 flex justify-center items-center h-8 rounded-xl text-sm shrink-0 font-medium
 -                         ${activeTab === tab.key && 'bg-components-main-nav-nav-button-bg-active shadow-md'}
 -                       `}
 -             onClick={() => setActiveTab(tab.key as AppIconType)}
 -           >
 -             {tab.icon}   {tab.label}
 -           </button>
 -         ))}
 -       </div>
 -     </div>}
 - 
 -     <Divider className='m-0' />
 - 
 -     <EmojiPickerInner className={activeTab === 'emoji' ? 'block' : 'hidden'} onSelect={handleSelectEmoji} />
 -     <Uploader className={activeTab === 'image' ? 'block' : 'hidden'} onImageCropped={handleImageCropped} />
 - 
 -     <Divider className='m-0' />
 -     <div className='w-full flex items-center justify-center p-3 gap-2'>
 -       <Button className='w-full' onClick={() => onClose?.()}>
 -         {t('app.iconPicker.cancel')}
 -       </Button>
 - 
 -       <Button variant="primary" className='w-full' disabled={uploading} loading={uploading} onClick={handleSelect}>
 -         {t('app.iconPicker.ok')}
 -       </Button>
 -     </div>
 -   </Modal>
 - }
 - 
 - export default AppIconPicker
 
 
  |