import React, { Component } from 'react'; import { Upload, Tooltip, Popover, Modal, Progress, message, Spin, Result } from 'antd'; import CopyToClipboard from 'react-copy-to-clipboard'; import { injectIntl } from 'react-intl'; import * as AntdIcons from '@ant-design/icons'; const allIcons: { [key: string]: any; } = AntdIcons; const { Dragger } = Upload; interface AntdIconClassifier { load: Function; predict: Function; } declare global { interface Window { antdIconClassifier: AntdIconClassifier; } } interface PicSearcherProps { intl: any; } interface PicSearcherState { loading: boolean; modalVisible: boolean; popoverVisible: boolean; icons: Array; fileList: Array; error: boolean; modelLoaded: boolean; } interface iconObject { type: string; score: number; } class PicSearcher extends Component { state = { loading: false, modalVisible: false, popoverVisible: false, icons: [], fileList: [], error: false, modelLoaded: false, }; componentDidMount() { this.loadModel(); this.setState({ popoverVisible: !localStorage.getItem('disableIconTip') }); } componentWillUnmount() { document.removeEventListener('paste', this.onPaste); } loadModel = () => { const script = document.createElement('script'); script.onload = async () => { await window.antdIconClassifier.load(); this.setState({ modelLoaded: true }); document.addEventListener('paste', this.onPaste); }; script.src = 'https://cdn.jsdelivr.net/gh/lewis617/antd-icon-classifier@0.0/dist/main.js'; document.head.appendChild(script); }; onPaste = (event: ClipboardEvent) => { const items = event.clipboardData && event.clipboardData.items; let file = null; if (items && items.length) { for (let i = 0; i < items.length; i += 1) { if (items[i].type.indexOf('image') !== -1) { file = items[i].getAsFile(); break; } } } if (file) this.uploadFile(file); }; uploadFile = (file: File) => { this.setState(() => ({ loading: true })); const reader: FileReader = new FileReader(); reader.onload = () => { this.toImage(reader.result).then(this.predict); this.setState(() => ({ fileList: [{ uid: 1, name: file.name, status: 'done', url: reader.result }], })); }; reader.readAsDataURL(file); }; toImage = (url: any) => new Promise(resolve => { const img = new Image(); img.setAttribute('crossOrigin', 'anonymous'); img.src = url; img.onload = function onload() { resolve(img); }; }); predict = (imgEl: any) => { try { let icons = window.antdIconClassifier.predict(imgEl); if (gtag && icons.length >= 1) { gtag('event', 'icon', { event_category: 'search-by-image', event_label: icons[0].className, }); } icons = icons.map((i: any) => ({ score: i.score, type: i.className.replace(/\s/g, '-') })); this.setState(() => ({ icons, loading: false, error: false })); } catch (err) { this.setState(() => ({ loading: false, error: true })); } }; toggleModal = () => { this.setState(prev => ({ modalVisible: !prev.modalVisible, popoverVisible: false, fileList: [], icons: [], })); if (!localStorage.getItem('disableIconTip')) { localStorage.setItem('disableIconTip', 'true'); } }; onCopied = (text: string) => { message.success( {text} copied 🎉 , ); }; render() { const { intl: { messages }, } = this.props; const { modalVisible, popoverVisible, icons, fileList, loading, modelLoaded, error, } = this.state; return (
{modelLoaded || (
)} {modelLoaded && ( this.uploadFile(o.file)} fileList={fileList} showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }} >

{messages['app.docs.components.icon.pic-searcher.upload-text']}

{messages['app.docs.components.icon.pic-searcher.upload-hint']}

)}
{icons.length > 0 && (
{messages['app.docs.components.icon.pic-searcher.result-tip']}
)} {icons.length > 0 && ( )} {icons.map((icon: iconObject) => { const { type } = icon; const iconName = `${type .split('-') .map(str => `${str[0].toUpperCase()}${str.slice(1)}`) .join('')}Outlined`; return ( ); })}
{messages['app.docs.components.icon.pic-searcher.th-icon']} {messages['app.docs.components.icon.pic-searcher.th-score']}
`} onCopy={this.onCopied}> {React.createElement(allIcons[iconName])}
{error && ( )}
); } } export default injectIntl(PicSearcher);