Source: feedback/Character.js

import { useSelector } from "react-redux"
import { SitePal } from "../../utils";
import { emptyObject, useVariables } from "../../_core";
import { useEffect } from "react";
import { useState } from "react";

/**
 * Componente que renderiza un character del sitio sitepal.com
 * @name Reactor.Components.Feedback.Character
 * @param {string} embed Embed con los datos del Character generados en la cuenta SitePal
 * @param {string} variable 
 *  Variable con la funcion que se quiere llamar y los parametros dentro de un array. Por ejemplo:
 *  {
 *    guid: "dkg2-kjgwpzdndge-ejhcjjkds"
 *    fn: "sayText", 
 *    params: ["", 3, 1, 3, "S", 1]
 *  }
 *  guid: sirve para poder llamar dos veces la misma funcion
 *  fn: la funcion de sitepal que se quiere llamar
 *  params: los parametros de la funcion
 * @param {string} [context = "global"] Contexto donde se encuentra la variable
 * @class
 * @example
<style>
  div.sitepal-wrapper{
    height: 500px;
    width:300px;
  }
</style>
<div style="height: 500px;min-width:300px;width: 100%;display: flex;flex-direction: column;align-items: center;">
  <character_load_script variable="loader" context="gpt">
    <if variable="loader.loaded" context="gpt" type="boolean">
      <condition value="true" type="boolean">
        <character 
          embed='3432155,500,300,"",1,1,2722664,0,1,1,"WSGmJ3ScqO8d4Zop1cuILz7q4In5k6q2",0,1' 
          variable="character" 
          context="gpt" 
        ></character>
        <a href="EjemplosCharacter" data='{"action": "say1"}' target="operation">Hablar</a>
      </condition>  
      <condition value="false" type="boolean">
        <p>Cargando...</p>
      </condition>  
    </if>
    <if variable="loader.error" context="gpt" type="boolean">
      <condition value="true" type="boolean">
        <p>Ops, ocurrió un error</p>
      </condition>  
    </if>
  </character_load_script>
</div>
 */

const fnCallerDefault = {guid: "", fn: null, params: []}

export const Character = ({variable, context, embed, children}) => {

  const [ loaded, setLoaded ] = useState(false);

  const fnCaller = useSelector(state => {
    const c = state.app.variables[context];
    const v = !!c ? c[variable] : null;
    if (!v) {
      return fnCallerDefault;
    }
    if (typeof v == "object") {
      return {...fnCallerDefault, ...v };
    }
  });

  useEffect(() => {
    if(!loaded && !!fnCaller.fn) {
      const timer = setTimeout(()=>{
        execFunction(fnCaller);
      }, 100);
      return () => clearTimeout(timer);
    }
    if(!loaded) return;
    execFunction(fnCaller);
  }, [loaded, fnCaller])

  const handleLoad = () => {
    setLoaded(true);
  }

  return (
    <>
      <SitePal
        embed={embed}
        onLoad={handleLoad}
      />
      {children}
    </>
  )
}

const execFunction = (fnCaller) => {
  if(!fnCaller.fn) return;
  if(!!window[fnCaller.fn]){
    try{
      window[fnCaller.fn].apply(null, fnCaller.params)
    }catch(e){
    }
  }
}


// aparte

// hay otros parametros

// 'S', 'P', 'D'

// a los que les podes aplicar un valor

//  sayText("La demo ha finalizado!... Vuelvo a mi estado inicial",5,2,3,'S',0.8);

// 16:27
// despues pasame la cuenta de sitepal y lo miro bien

// Hillbilly, 16:28
// el ultimo "S", 0.8

// 16:28
// si

// Hillbilly, 16:28
// se refiere a un 80% de la velocidad normal 

// 16:28
// ok
// y el "S"?

// Hillbilly, 16:28
// "S" speed

// "P" Pitch

// "D" duration

// 16:29
// ah
// que raro eso
// podes combinarlos?

// Hillbilly, 16:29
// si

// 'S',0.8,'P',2

// podes hacer eso 

// 16:30
// ok
// lo ponemos en un object
// json
// {"S": 0.8, "P": 2}
// yo lo mando como me pusiste ahi