Skip to content
TemplateContext.tsx 3.34 KiB
Newer Older
Grant's avatar
Grant committed
import {
  PropsWithChildren,
  createContext,
  useContext,
  useEffect,
Grant's avatar
Grant committed
  useState,
} from "react";
import { IRouterData, Router } from "../lib/router";
Grant's avatar
Grant committed
import { KeybindManager } from "../lib/keybinds";
Grant's avatar
Grant committed
import { TemplateStyle } from "../lib/template";

interface ITemplate {
  /**
   * If the template is being used
   */
  enable: boolean;

  /**
   * URL of the template image being used
   */
  url?: string;

  /**
   * Width of the template being displayed
   *
   * @default min(template.width,canvas.width)
   */
  width?: number;

  x: number;
  y: number;
  opacity: number;
Grant's avatar
Grant committed
  style: TemplateStyle;
  showMobileTools: boolean;

  setEnable(v: boolean): void;
  setURL(v?: string): void;
  setWidth(v?: number): void;
  setX(v: number): void;
  setY(v: number): void;
  setOpacity(v: number): void;
Grant's avatar
Grant committed
  setStyle(style: TemplateStyle): void;
  setShowMobileTools(v: boolean): void;
}

const templateContext = createContext<ITemplate>({} as any);

export const useTemplateContext = () => useContext(templateContext);

export const TemplateContext = ({ children }: PropsWithChildren) => {
Grant's avatar
Grant committed
  const routerData = Router.get();
  const [enable, setEnable] = useState(!!routerData.template?.url);
  const [url, setURL] = useState<string | undefined>(routerData.template?.url);
  const [width, setWidth] = useState<number | undefined>(
    routerData.template?.width
  );
  const [x, setX] = useState(routerData.template?.x || 0);
  const [y, setY] = useState(routerData.template?.y || 0);
  const [opacity, setOpacity] = useState(100);
Grant's avatar
Grant committed
  const [style, setStyle] = useState<TemplateStyle>(
    routerData.template?.style || "ONE_TO_ONE"
  );
  const [showMobileTools, setShowMobileTools] = useState(true);
  const initAt = useRef<number>();

Grant's avatar
Grant committed
  useEffect(() => {
    initAt.current = Date.now();

Grant's avatar
Grant committed
    const handleNavigate = (data: IRouterData) => {
      if (data.template) {
        setEnable(true);
        setURL(data.template.url);
        setWidth(data.template.width);
        setX(data.template.x || 0);
        setY(data.template.y || 0);
Grant's avatar
Grant committed
        setStyle(data.template.style || "ONE_TO_ONE");
Grant's avatar
Grant committed
      } else {
        setEnable(false);
      }
    };

Grant's avatar
Grant committed
    const handleToggleTemplate = () => {
      setEnable((en) => !en);
    };

Grant's avatar
Grant committed
    Router.on("navigate", handleNavigate);
Grant's avatar
Grant committed
    KeybindManager.on("TOGGLE_TEMPLATE", handleToggleTemplate);
Grant's avatar
Grant committed

    return () => {
      Router.off("navigate", handleNavigate);
Grant's avatar
Grant committed
      KeybindManager.on("TOGGLE_TEMPLATE", handleToggleTemplate);
Grant's avatar
Grant committed
    };
  }, []);

  useEffect(() => {
Grant's avatar
Grant committed
    Router.setTemplate({ enabled: enable, width, x, y, url, style });

    if (!initAt.current) {
      console.debug("TemplateContext updating router but no initAt");
    } else if (Date.now() - initAt.current < 2 * 1000) {
      console.debug(
        "TemplateContext updating router too soon after init",
        Date.now() - initAt.current
      );
    }

    if (initAt.current && Date.now() - initAt.current > 2 * 1000)
      Router.queueUpdate();
Grant's avatar
Grant committed
  }, [enable, width, x, y, url, style]);
  return (
    <templateContext.Provider
      value={{
        enable,
        setEnable,
        url,
        setURL,
        width,
        setWidth,
        x,
        setX,
        y,
        setY,
        opacity,
        setOpacity,
Grant's avatar
Grant committed
        style,
        setStyle,
        showMobileTools,
        setShowMobileTools,
      }}
    >
      {children}
    </templateContext.Provider>
  );
};