Skip to content
AppContext.tsx 2.69 KiB
Newer Older
Grant's avatar
Grant committed
import {
Grant's avatar
Grant committed
  PropsWithChildren,
  createContext,
  useContext,
  useEffect,
  useState,
} from "react";
Grant's avatar
Grant committed
import {
Grant's avatar
Grant committed
  AuthSession,
Grant's avatar
Grant committed
  ClientConfig,
  IAppContext,
  ICanvasPosition,
  IPosition,
Grant's avatar
Grant committed
} from "@sc07-canvas/lib/src/net";
Grant's avatar
Grant committed
import Network from "../lib/network";

const appContext = createContext<IAppContext>({} as any);

export const useAppContext = () => useContext(appContext);

export const AppContext = ({ children }: PropsWithChildren) => {
  const [config, setConfig] = useState<ClientConfig>(undefined as any);
  const [auth, setAuth] = useState<AuthSession>();
Grant's avatar
Grant committed
  const [canvasPosition, setCanvasPosition] = useState<ICanvasPosition>();
Grant's avatar
Grant committed
  const [cursorPosition, setCursorPosition] = useState<IPosition>();
Grant's avatar
Grant committed

Grant's avatar
Grant committed
  // --- settings ---
  const [loadChat, _setLoadChat] = useState(false);

Grant's avatar
Grant committed
  const [pixels, setPixels] = useState({ available: 0 });
Grant's avatar
Grant committed
  const [undo, setUndo] = useState<{ available: true; expireAt: number }>();
Grant's avatar
Grant committed

  // overlays visible
  const [settingsSidebar, setSettingsSidebar] = useState(false);

Grant's avatar
Grant committed
  useEffect(() => {
Grant's avatar
Grant committed
    function loadSettings() {
Grant's avatar
Grant committed
      setLoadChat(
        localStorage.getItem("matrix.enable") === null
          ? true
          : localStorage.getItem("matrix.enable") === "true"
      );
Grant's avatar
Grant committed
    }

Grant's avatar
Grant committed
    function handleConfig(config: ClientConfig) {
      console.info("Server sent config", config);
      setConfig(config);
    }

    function handleUser(user: AuthSession) {
      setAuth(user);
    }

Grant's avatar
Grant committed
    function handlePixels(pixels: { available: number }) {
      setPixels(pixels);
    }

Grant's avatar
Grant committed
    function handleUndo(
      data: { available: false } | { available: true; expireAt: number }
    ) {
      if (data.available) {
        setUndo({ available: true, expireAt: data.expireAt });
      } else {
        setUndo(undefined);
      }
    }

Grant's avatar
Grant committed
    Network.on("user", handleUser);
    Network.on("config", handleConfig);
Grant's avatar
Grant committed
    Network.waitFor("pixels").then(([data]) => handlePixels(data));
    Network.on("pixels", handlePixels);
Grant's avatar
Grant committed
    Network.on("undo", handleUndo);
Grant's avatar
Grant committed

    Network.socket.connect();

Grant's avatar
Grant committed
    loadSettings();

Grant's avatar
Grant committed
    return () => {
      Network.off("user", handleUser);
      Network.off("config", handleConfig);
Grant's avatar
Grant committed
      Network.off("pixels", handlePixels);
Grant's avatar
Grant committed
    };
  }, []);

Grant's avatar
Grant committed
  const setLoadChat = (v: boolean) => {
    _setLoadChat(v);
    localStorage.setItem("matrix.enable", v ? "true" : "false");
  };

Grant's avatar
Grant committed
  return (
Grant's avatar
Grant committed
    <appContext.Provider
Grant's avatar
Grant committed
      value={{
        config,
        user: auth,
        canvasPosition,
        setCanvasPosition,
        cursorPosition,
        setCursorPosition,
Grant's avatar
Grant committed
        pixels,
        settingsSidebar,
        setSettingsSidebar,
Grant's avatar
Grant committed
        undo,
Grant's avatar
Grant committed
        loadChat,
        setLoadChat,
Grant's avatar
Grant committed
      }}
Grant's avatar
Grant committed
    >
Grant's avatar
Grant committed
      {config ? children : "Loading..."}
    </appContext.Provider>
  );
};