import React, {useEffect, useState, useRef} from 'react'; import styled from 'styled-components'; import {useTranslation} from 'react-i18next'; import fetch from 'isomorphic-unfetch'; import {TiArrowSync} from 'react-icons/ti'; import {capitalize} from '../util/text'; import {mobile} from '../util/css'; type Modifier = (word: string) => string; const maximumCount = 3; const modifiers: Modifier[] = [ (word) => `${capitalize(word)}ify`, (word) => `lib${lower(word)}`, (word) => `Omni${capitalize(word)}`, (word) => `${capitalize(word)}Lab`, (word) => `${capitalize(word)}Kit`, (word) => `Open${capitalize(word)}`, (word) => `${capitalize(word)}box`, (word) => `Insta${lower(word)}`, (word) => `${capitalize(word)}Hub`, (word) => `Cloud${capitalize(word)}`, (word) => `quick${lower(word)}`, (word) => `fast${lower(word)}`, (word) => `super-${lower(word)}`, (word) => `Hyper${capitalize(word)}`, (word) => `${capitalize(word)}Go`, (word) => `${lower(word)}-io`, (word) => `Go${capitalize(word)}`, (word) => `${capitalize(word)}X`, (word) => `${capitalize(word)}time`, (word) => `${capitalize(word)}flow`, (word) => `${capitalize(word)}ful`, (word) => `${capitalize(word)}ery`, (word) => `${lower(word)}ly`, (word) => `${lower(word)}joy`, (word) => `${capitalize(word)}Hunt`, (word) => `${capitalize(word)}gram`, (word) => `${capitalize(word)}base`, (word) => `${capitalize(word)}API`, (word) => `${capitalize(word)}note`, (word) => `In${capitalize(word)}`, (word) => `Uni${lower(word)}`, (word) => `${capitalize(word)}`, ]; function lower(word: string) { return word.toLowerCase(); } function shuffleArray(array: any[]) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); const temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; } function sampleFromArray(array: any[], maximum: number) { return shuffleArray(array).slice(0, maximum); } function modifyWord(word: string) { return modifiers[Math.floor(Math.random() * modifiers.length)](word); } function fillArray(array: any[], filler: string, maximum: number) { const deficit = maximum - array.length; if (deficit > 0) { array = [...array, ...Array(deficit).fill(filler)]; } return array; } async function findSynonyms(word: string) { try { const response = await fetch( `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&dt=ss&ie=UTF-8&oe=UTF-8&dj=1&q=${encodeURIComponent( word, )}`, ); const json: { synsets: Array<{entry: Array<{synonym: string[]}>}>; } = await response.json(); const synonyms = Array.from( new Set( json.synsets.reduce( (sum, synset) => [...sum, ...synset.entry.map((e) => e.synonym[0])], [] as string[], ), ), ).filter((word) => !word.match(/[\s-]/)); return synonyms; } catch (err) { return []; } } const Suggestion: React.FC<{ query: string; onSubmit: (name: string) => void; }> = ({query, onSubmit}) => { const {t} = useTranslation(); const synonymRef = useRef([]); const [bestWords, setBestWords] = useState([]); function shuffle() { const best = fillArray( sampleFromArray(synonymRef.current, maximumCount), query, maximumCount, ).map((word) => modifyWord(word)); setBestWords(best); } function applyQuery(name: string) { onSubmit(name); } useEffect(() => { const fn = async () => { if (query && query.length > 0) { const synonyms = await findSynonyms(query); synonymRef.current = synonyms; const best = fillArray( sampleFromArray(synonyms, maximumCount), query, maximumCount, ).map((word) => modifyWord(word)); setBestWords(best); } }; fn(); }, [query]); return ( {t('try')} {bestWords && bestWords.map((name) => ( applyQuery(name)}> {name} ))} ); }; export default Suggestion; const Container = styled.div` margin-bottom: 10px; display: flex; flex-direction: column; align-items: center; flex-wrap: wrap; justify-content: center; `; const Title = styled.div` margin-top: 15px; padding: 5px 12px; color: gray; border: 1px solid gray; border-radius: 2em; `; const Items = styled.div` margin-top: 2px; display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; ${mobile} { flex-direction: column; align-items: center; } `; const Item = styled.div` margin-top: 8px; margin-right: 14px; cursor: pointer; font-weight: bold; font-family: monospace; border-bottom: 1px dashed black; color: black; ${mobile} { margin-right: 0; } `; const Icon = styled(Item)` display: flex; align-items: center; border-bottom: none; `;