All files / client/src/hooks use-experimental-workspace-layout.ts

94.28% Statements 33/35
50% Branches 2/4
100% Functions 11/11
93.75% Lines 30/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87                              3x 3x             3x 3x                 12x 12x 12x       12x 3x 1x 1x   3x 3x     12x 1x 1x   1x     12x 2x 2x 2x 2x   2x       12x 1x 1x 1x 1x       12x   12x                      
import { useCallback, useEffect, useMemo, useState } from "react";
import {
  DEFAULT_WORKSPACE_COLUMN_SIZES,
  DEFAULT_EXPERIMENTAL_WORKSPACE_LAYOUT,
  EXPERIMENTAL_WORKSPACE_COLUMNS_KEY,
  EXPERIMENTAL_WORKSPACE_LAYOUT_CHANGE_EVENT,
  EXPERIMENTAL_WORKSPACE_LAYOUT_KEY,
  getVisibleWorkspaceColumns,
  parseWorkspaceColumnVisibility,
  type WorkspaceColumn,
  type WorkspaceColumnSizes,
  type WorkspaceColumnVisibility,
} from "@/lib/experimental-workspace-layout";
 
function readEnabled(): boolean {
  try {
    return globalThis.localStorage.getItem(EXPERIMENTAL_WORKSPACE_LAYOUT_KEY) === "1";
  } catch {
    return DEFAULT_EXPERIMENTAL_WORKSPACE_LAYOUT;
  }
}
 
function readVisibility(): WorkspaceColumnVisibility {
  try {
    return parseWorkspaceColumnVisibility(
      globalThis.localStorage.getItem(EXPERIMENTAL_WORKSPACE_COLUMNS_KEY),
    );
  } catch {
    return parseWorkspaceColumnVisibility(null);
  }
}
 
export function useExperimentalWorkspaceLayout() {
  const [enabled, setEnabled] = useState(readEnabled);
  const [visibility, setVisibility] = useState<WorkspaceColumnVisibility>(readVisibility);
  const [sizes, setSizes] = useState<WorkspaceColumnSizes>({
    ...DEFAULT_WORKSPACE_COLUMN_SIZES,
  });
 
  useEffect(() => {
    const onChange = (event: Event) => {
      const value = (event as CustomEvent<{ value?: boolean }>).detail?.value;
      Eif (typeof value === "boolean") setEnabled(value);
    };
    globalThis.addEventListener(EXPERIMENTAL_WORKSPACE_LAYOUT_CHANGE_EVENT, onChange);
    return () => globalThis.removeEventListener(EXPERIMENTAL_WORKSPACE_LAYOUT_CHANGE_EVENT, onChange);
  }, []);
 
  const setExperimentalEnabled = useCallback((value: boolean) => {
    try {
      globalThis.localStorage.setItem(EXPERIMENTAL_WORKSPACE_LAYOUT_KEY, value ? "1" : "0");
    } catch {}
    setEnabled(value);
  }, []);
 
  const setColumnVisible = useCallback((column: WorkspaceColumn, value: boolean) => {
    setVisibility((current) => {
      const next = { ...current, [column]: value };
      try {
        globalThis.localStorage.setItem(EXPERIMENTAL_WORKSPACE_COLUMNS_KEY, JSON.stringify(next));
      } catch {}
      return next;
    });
  }, []);
 
  const restoreDefaultLayout = useCallback(() => {
    const next = { code: true, simulation: true, tutor: false } satisfies WorkspaceColumnVisibility;
    setVisibility(next);
    try {
      globalThis.localStorage.setItem(EXPERIMENTAL_WORKSPACE_COLUMNS_KEY, JSON.stringify(next));
    } catch {}
  }, []);
 
  const visibleColumns = useMemo(() => getVisibleWorkspaceColumns(visibility), [visibility]);
 
  return {
    enabled,
    setExperimentalEnabled,
    visibility,
    setColumnVisible,
    restoreDefaultLayout,
    visibleColumns,
    sizes,
    setSizes,
  };
}