import React , { useState , useCallback , useEffect } from 'react' ; import Creepyface from 'react-creepyface' ; import Loader from './Loader' ; import { FaceIcon } from './Icon' ; import { angles , Angle } from '../redux/types' ; import hash from 'string-hash' ; import 'creepyface-firefly' ; import { Size } from '../backend/resize' ; import { useMountedState } from 'react-use' ; const noop = ( ) => { } ; const url = ( id , namespace ? , size ? ) => ( name ) => `/img/${ id }/${ name }${ size ? '/' + size : '' }${ namespace ? '?namespace=' + namespace : '' }` ; export type Images = { src : string ; hover : string ; looks : { angle : Angle ; src : string ; } [ ] ; } ; export const getHostedImages = ( id = 0 , namespace ? , size ? ) : Images => { const getUrl = url ( id , namespace , size ) ; return { src : getUrl ( 'serious' ) , hover : getUrl ( 'hover' ) , looks : angles . map ( ( angle ) => ( { angle , src : getUrl ( `${ angle }` ) } ) ) , } ; } ; export function AsyncCreepyFace ( props ) { const [ images , setImages ] = useState < Images | null > ( null ) ; const isMounted = useMountedState ( ) ; const { getImages , id } = props ; useEffect ( ( ) => { setImages ( null ) ; getImages ( id ) . then ( ( images ) => { if ( isMounted ( ) ) { setImages ( images ) ; } } ) ; } , [ getImages , id , isMounted ] ) ; return ( < CreepyFace id = { `${ props . id }` } alt = { props . alt } images = { images } points = { props . points } timeToDefault = { props . timeToDefault } onSelect = { props . onSelect } / > ) ; } export default function CreepyFace ( props ) { const { id , alt , images , hidden , points , timeToDefault , onSelect = noop , onChange = noop , onLoad = noop , } = props ; const [ firstAttach , setFirstAttach ] = useState ( true ) ; const [ attached , setAttached ] = useState ( false ) ; const [ loaded , setLoaded ] = useState ( false ) ; const onAttach = useCallback ( ( ) => { setAttached ( true ) ; setFirstAttach ( false ) ; onLoad ( ) ; } , [ onLoad ] ) ; const onDetach = useCallback ( ( ) => { setAttached ( false ) ; } , [ ] ) ; const onDebug = useCallback ( ( { src } ) => onChange ( src ) , [ onChange ] ) ; return ( < span className = "creepy" > { ! hidden && images && ( < Creepyface alt = { alt } src = { images . src } options = { { hover : images . hover , looks : images . looks , points , timeToDefault , optimizePerformance : true , onAttach , onDetach , onDebug , } } onClick = { onSelect } onLoad = { ( ) => setLoaded ( true ) } />)} { ( ! loaded || firstAttach || hidden || ! images ) && ( < div className = "placeholder" > < FaceIcon seed = { hash ( id ?? images ?. src ?? '' ) } /> < /div>)} { ! hidden && ( ! attached || ! loaded ) && < Loader />} < /span>); }