Skip to content

Commit

Permalink
Fix Vite HMR errors (#64)
Browse files Browse the repository at this point in the history
* Separate vanilla JS functions into their own files

* Refactor floating panel context, run prettier

* Add build

* Move context managers back into their files and change HMR port to 1025

* Add build

---------

Co-authored-by: Brent Yi <[email protected]>
  • Loading branch information
jonahbedouch and brentyi committed Jul 11, 2023
1 parent 831f743 commit d0e3ccd
Show file tree
Hide file tree
Showing 22 changed files with 829 additions and 808 deletions.
3 changes: 2 additions & 1 deletion viser/client/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
plugins: ["react", "@typescript-eslint", "react-refresh"],
ignorePatterns: ["build/", ".eslintrc.js"],
rules: {
// https://github.com/jsx-eslint/eslint-plugin-react/issues/3423
Expand All @@ -37,5 +37,6 @@ module.exports = {
skipUndeclared: true,
},
],
"react-refresh/only-export-components": "warn"
},
};

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions viser/client/build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
-->
<link rel="manifest" href="/manifest.json" />
<title>Viser</title>
<script type="module" crossorigin src="/assets/index-10ab1cd1.js"></script>
<script type="module" crossorigin src="/assets/index-27c5f284.js"></script>
<link rel="stylesheet" href="/assets/index-a02dfc21.css">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

</body>
</html>
1 change: 1 addition & 0 deletions viser/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"browserslist-to-esbuild": "^1.2.0",
"eslint": "^8.43.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-refresh": "^0.4.1",
"typescript": "^5.0.4",
"vite-plugin-eslint": "^1.8.1"
}
Expand Down
262 changes: 262 additions & 0 deletions viser/client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
import {
AdaptiveDpr,
AdaptiveEvents,
CameraControls,
Environment,
} from "@react-three/drei";
import * as THREE from "three";
import { Canvas, useThree } from "@react-three/fiber";
import {
EffectComposer,
Outline,
Selection,
} from "@react-three/postprocessing";
import { BlendFunction, KernelSize } from "postprocessing";

import { SynchronizedCameraControls } from "./CameraControls";
import {
Aside,
Box,
MantineProvider,
MediaQuery,
ScrollArea,
useMantineTheme,
} from "@mantine/core";
import React from "react";

import { SceneNodeThreeObject, UseSceneTree } from "./SceneTree";

import { useSceneTreeState } from "./SceneTreeState";

import "./index.css";

import ControlPanel, { ConnectionStatus } from "./ControlPanel/ControlPanel";
import { UseGui, useGuiState } from "./ControlPanel/GuiState";
import { searchParamKey } from "./SearchParamsUtils";
import WebsocketInterface from "./WebsocketInterface";

import FloatingPanel from "./ControlPanel/FloatingPanel";
import { Titlebar } from "./Titlebar";
import BottomPanel from "./ControlPanel/BottomPanel";
import { useMediaQuery } from "@mantine/hooks";

type ViewerContextContents = {
useSceneTree: UseSceneTree;
useGui: UseGui;
websocketRef: React.MutableRefObject<WebSocket | null>;
canvasRef: React.MutableRefObject<HTMLCanvasElement | null>;
sceneRef: React.MutableRefObject<THREE.Scene | null>;
cameraRef: React.MutableRefObject<THREE.PerspectiveCamera | null>;
cameraControlRef: React.MutableRefObject<CameraControls | null>;
nodeAttributesFromName: React.MutableRefObject<{
[name: string]:
| undefined
| {
wxyz?: [number, number, number, number];
position?: [number, number, number];
visibility?: boolean;
};
}>;
};
export const ViewerContext = React.createContext<null | ViewerContextContents>(
null
);

THREE.ColorManagement.enabled = true;

function SingleViewer() {
// Default server logic.
function getDefaultServerFromUrl() {
// https://localhost:8080/ => ws://localhost:8080
// https://localhost:8080/?server=some_url => ws://localhost:8080
let server = window.location.href;
server = server.replace("http://", "ws://");
server = server.split("?")[0];
if (server.endsWith("/")) server = server.slice(0, -1);
return server;
}
const servers = new URLSearchParams(window.location.search).getAll(
searchParamKey
);
const initialServer =
servers.length >= 1 ? servers[0] : getDefaultServerFromUrl();

// Values that can be globally accessed by components in a viewer.
const viewer: ViewerContextContents = {
useSceneTree: useSceneTreeState(),
useGui: useGuiState(initialServer),
websocketRef: React.useRef(null),
canvasRef: React.useRef(null),
sceneRef: React.useRef(null),
cameraRef: React.useRef(null),
cameraControlRef: React.useRef(null),
// Scene node attributes that aren't placed in the zustand state, for performance reasons.
nodeAttributesFromName: React.useRef({}),
};
const fixed_sidebar = viewer.useGui((state) => state.theme.fixed_sidebar);
return (
<ViewerContext.Provider value={viewer}>
<Titlebar />
<Box
sx={{
width: "100%",
height: "1px",
position: "relative",
flex: "1 0 auto",
}}
>
<WebsocketInterface />
<MediaQuery smallerThan={"xs"} styles={{ right: 0, bottom: "3.5em" }}>
<Box
sx={(theme) => ({
top: 0,
bottom: 0,
left: 0,
right: fixed_sidebar ? "20em" : 0,
position: "absolute",
backgroundColor:
theme.colorScheme === "light" ? "#fff" : theme.colors.dark[9],
})}
>
<ViewerCanvas />
</Box>
</MediaQuery>
<Panel fixed_sidebar={fixed_sidebar} />
</Box>
</ViewerContext.Provider>
);
}
function Panel(props: { fixed_sidebar: boolean }) {
const theme = useMantineTheme();
const xsQuery = useMediaQuery(`(max-width: ${theme.breakpoints.xs})`);
if (xsQuery) {
return (
<BottomPanel>
<BottomPanel.Handle>
<ConnectionStatus />
</BottomPanel.Handle>
<BottomPanel.Contents>
<ControlPanel />
</BottomPanel.Contents>
</BottomPanel>
);
} else if (props.fixed_sidebar) {
return (
<Aside
sx={(theme) => ({
width: "20em",
boxSizing: "border-box",
right: 0,
position: "absolute",
top: "0em",
bottom: "0em",
borderLeft: "1px solid",
borderColor:
theme.colorScheme == "light"
? theme.colors.gray[4]
: theme.colors.dark[4],
})}
>
<ScrollArea type="always" sx={{ height: "100%" }}>
<Box
p="sm"
sx={(theme) => ({
backgroundColor:
theme.colorScheme == "dark"
? theme.colors.dark[5]
: theme.colors.gray[1],
lineHeight: "1.5em",
fontWeight: 400,
})}
>
<ConnectionStatus />
</Box>
<ControlPanel />
</ScrollArea>
</Aside>
);
} else {
return (
<FloatingPanel>
<FloatingPanel.Handle>
<ConnectionStatus />
</FloatingPanel.Handle>
<FloatingPanel.Contents>
<ControlPanel />
</FloatingPanel.Contents>
</FloatingPanel>
);
}
}

function ViewerCanvas() {
const viewer = React.useContext(ViewerContext)!;
return (
<Canvas
camera={{ position: [3.0, 3.0, -3.0] }}
gl={{ preserveDrawingBuffer: true }}
style={{
position: "relative",
zIndex: 0,
width: "100%",
height: "100%",
}}
performance={{ min: 0.95 }}
ref={viewer.canvasRef}
>
<AdaptiveDpr pixelated />
<AdaptiveEvents />
<SceneContextSetter />
<SynchronizedCameraControls />
<Selection>
<SceneNodeThreeObject name="" />
<EffectComposer enabled={true} autoClear={false}>
<Outline
hiddenEdgeColor={0xfbff00}
visibleEdgeColor={0xfbff00}
blendFunction={BlendFunction.SCREEN} // set this to BlendFunction.ALPHA for dark outlines
kernelSize={KernelSize.MEDIUM}
edgeStrength={30.0}
height={480}
blur
/>
</EffectComposer>
</Selection>
<Environment path="/hdri/" files="potsdamer_platz_1k.hdr" />
</Canvas>
);
}

/** Component for helping us set the scene reference. */
function SceneContextSetter() {
const { sceneRef, cameraRef } = React.useContext(ViewerContext)!;
sceneRef.current = useThree((state) => state.scene);
cameraRef.current = useThree(
(state) => state.camera as THREE.PerspectiveCamera
);
return <></>;
}

export function Root() {
return (
<MantineProvider
withGlobalStyles
withNormalizeCSS
theme={{
colorScheme: "light",
}}
>
<Box
sx={{
width: "100%",
height: "100%",
position: "relative",
display: "flex",
flexDirection: "column",
}}
>
<SingleViewer />
</Box>
</MantineProvider>
);
}
4 changes: 2 additions & 2 deletions viser/client/src/CameraControls.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ViewerContext } from ".";
import { makeThrottledMessageSender } from "./WebsocketInterface";
import { ViewerContext } from "./App";
import { makeThrottledMessageSender } from "./WebsocketFunctions";
import { CameraControls } from "@react-three/drei";
import { useThree } from "@react-three/fiber";
import * as holdEvent from "hold-event";
Expand Down
8 changes: 4 additions & 4 deletions viser/client/src/ControlPanel/BottomPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IconCaretDown } from "@tabler/icons-react";
import React from "react";
import { isMouseEvent, isTouchEvent, mouseEvents, touchEvents } from "../Utils";

const BottomPanelRefContext =
export const BottomPanelRefContext =
React.createContext<React.RefObject<HTMLDivElement> | null>(null);

const pagePercent = (start: number, end: number) => {
Expand Down Expand Up @@ -56,7 +56,7 @@ export default function BottomPanel({
</BottomPanelRefContext.Provider>
);
}
BottomPanel.Handle = function FloatingPanelHandle({
BottomPanel.Handle = function BottomPanelHandle({
children,
}: {
children: string | React.ReactNode;
Expand Down Expand Up @@ -191,13 +191,13 @@ BottomPanel.Handle = function FloatingPanelHandle({
);
};
/** Contents of a panel. */
BottomPanel.Contents = function FloatingPanelContents({
BottomPanel.Contents = function BottomPanelContents({
children,
}: {
children: string | React.ReactNode;
}) {
const panelWrapperRef = React.useContext(BottomPanelRefContext)!;
const contentRef = React.useRef<HTMLDivElement>(null);
const panelWrapperRef = React.useContext(BottomPanelRefContext)!;
React.useEffect(() => {
const panel = panelWrapperRef.current;
const content = contentRef.current;
Expand Down
2 changes: 1 addition & 1 deletion viser/client/src/ControlPanel/ControlPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ViewerContext } from "..";
import { ViewerContext } from "../App";
import GeneratedControls from "./Generated";
import SceneTreeTable from "./SceneTreeTable";
import ServerControls from "./Server";
Expand Down
5 changes: 4 additions & 1 deletion viser/client/src/ControlPanel/FloatingPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// @refresh reset

import { Box, Paper } from "@mantine/core";
import { IconCaretUp } from "@tabler/icons-react";
import React from "react";
import { isMouseEvent, isTouchEvent, mouseEvents, touchEvents } from "../Utils";

const FloatingPanelRefContext =
export const FloatingPanelRefContext =
React.createContext<React.RefObject<HTMLDivElement> | null>(null);

/** Root component for control panel. Parents a set of control tabs.
Expand Down Expand Up @@ -89,6 +91,7 @@ FloatingPanel.Handle = function FloatingPanelHandle({
Math.abs(panelPosition - parentSize + panelSize / 2.0)
? panelPosition
: panelPosition - parentSize;

const panelBoundaryPad = 15;
function setPanelLocation(x: number, y: number) {
const panel = panelWrapperRef.current;
Expand Down
4 changes: 2 additions & 2 deletions viser/client/src/ControlPanel/Generated.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ViewerContext } from "..";
import { makeThrottledMessageSender } from "../WebsocketInterface";
import { ViewerContext } from "../App";
import { makeThrottledMessageSender } from "../WebsocketFunctions";
import { GuiConfig } from "./GuiState";
import {
Accordion,
Expand Down
4 changes: 0 additions & 4 deletions viser/client/src/ControlPanel/GuiState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ export type GuiConfig =
| Messages.GuiAddVector2Message
| Messages.GuiAddVector3Message;

export function isGuiConfig(message: Messages.Message): message is GuiConfig {
return message.type.startsWith("GuiAdd");
}

interface GuiState {
theme: Messages.ThemeConfigurationMessage;
label: string;
Expand Down
2 changes: 1 addition & 1 deletion viser/client/src/ControlPanel/SceneTreeTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ViewerContext } from "..";
import { ViewerContext } from "../App";
import { ActionIcon, Modal } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import {
Expand Down
Loading

0 comments on commit d0e3ccd

Please sign in to comment.