import { useEffect, useState, useCallback, ChangeEvent, ClipboardEvent, MouseEventHandler, useRef, KeyboardEvent } from "react" import Image from 'next/image' import PasteIcon from '@/assets/images/paste.svg' import UploadIcon from '@/assets/images/upload.svg' import CameraIcon from '@/assets/images/camera.svg' import { useBing } from '@/lib/hooks/use-bing' import { cn } from '@/lib/utils' import { toast } from "react-hot-toast" interface ChatImageProps extends Pick, 'uploadImage'> {} const preventDefault: MouseEventHandler = (event) => { event.nativeEvent.stopImmediatePropagation() } const toBase64 = (file: File): Promise => new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsDataURL(file) reader.onload = () => resolve(reader.result as string) reader.onerror = reject }) export function ChatImage({ children, uploadImage }: React.PropsWithChildren) { const videoRef = useRef(null) const canvasRef = useRef(null) const mediaStream = useRef() const [panel, setPanel] = useState('none') const [inputUrl, setInputUrl] = useState('') const upload = useCallback((url: string) => { if (url) { uploadImage(url) } setPanel('none') }, [panel]) const onUpload = useCallback(async (event: ChangeEvent) => { const file = event.target.files?.[0] if (file) { const fileDataUrl = await toBase64(file) if (fileDataUrl) { upload(fileDataUrl) } } }, []) const onPaste = useCallback((event: ClipboardEvent) => { const pasteUrl = event.clipboardData.getData('text') ?? '' upload(pasteUrl) }, []) const onEnter = useCallback((event: KeyboardEvent) => { // @ts-ignore event.preventDefault() // @ts-ignore event.stopPropagation() if (/^https?:\/\/.+/.test(inputUrl)) { upload(inputUrl) } else { toast.error('请输入有效的图片链接') } }, [inputUrl]) const openVideo: MouseEventHandler = async (event) => { event.stopPropagation() setPanel('camera-mode') } const onCapture = () => { if (canvasRef.current && videoRef.current) { const canvas = canvasRef.current canvas.width = videoRef.current!.videoWidth canvas.height = videoRef.current!.videoHeight canvas.getContext('2d')?.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height) const cameraUrl = canvas.toDataURL('image/jpeg') upload(cameraUrl) } } useEffect(() => { const handleBlur = () => { if (panel !== 'none') { setPanel('none') } } document.addEventListener('click', handleBlur) return () => { document.removeEventListener('click', handleBlur) } }, [panel]) useEffect(() => { if (panel === 'camera-mode') { navigator.mediaDevices.getUserMedia({ video: true, audio: false }) .then(videoStream => { mediaStream.current = videoStream if (videoRef.current) { videoRef.current.srcObject = videoStream } }) } else { if (mediaStream.current) { mediaStream.current.getTracks().forEach(function(track) { track.stop() }) mediaStream.current = undefined } } }, [panel]) return (
panel === 'none' ? setPanel('normal') : setPanel('none')}>{children}

添加图像

paste setInputUrl(event.target.value.trim())} onKeyDownCapture={event => { if (event.key === 'Enter') { onEnter(event) } }} onClickCapture={(e) => e.stopPropagation()} />
{panel === 'camera-mode' &&
}
) }