From 00caa760e3e717326986b89732881d5da17831a3 Mon Sep 17 00:00:00 2001 From: noxware <7684329+noxware@users.noreply.github.com> Date: Sat, 12 Oct 2024 16:53:41 -0300 Subject: [PATCH] replace preact app with react app from the rust side --- companion/src/App.jsx | 151 ++++++++++++++++++++++++++++++++----- companion/src/main.jsx | 21 +++++- companion/vite.config.ts | 3 + src/js/companion.js | 156 --------------------------------------- src/web.rs | 2 +- 5 files changed, 155 insertions(+), 178 deletions(-) delete mode 100644 src/js/companion.js diff --git a/companion/src/App.jsx b/companion/src/App.jsx index fe65c09..3cc87ce 100644 --- a/companion/src/App.jsx +++ b/companion/src/App.jsx @@ -1,27 +1,138 @@ -import { useState } from "react"; +import React, { useState, useEffect } from "react"; + +function Area({ area, interactive }) { + return ( + +
{ + console.log("Mouse entered"); + }} + dangerouslySetInnerHTML={{ + __html: area.content, + }} + /> + + ); +} + +function MaskRect({ id, x, y, width, height, kind }) { + return ( + + ); +} function App() { - const [count, setCount] = useState(0); + const [windowWidth, setWindowWidth] = useState(window.innerWidth); + const [windowHeight, setWindowHeight] = useState(window.innerHeight); + const [mouseX, setMouseX] = useState(0); + const [mouseY, setMouseY] = useState(0); + const [areas, setAreas] = useState([]); + window.setAreas = setAreas; + + useEffect(() => { + const handleResize = () => { + setWindowWidth(window.innerWidth); + setWindowHeight(window.innerHeight); + }; + + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + useEffect(() => { + const handleMouseMove = (event) => { + setMouseX(event.clientX); + setMouseY(event.clientY); + }; + + // Because of the svg having no pointer events, only the canvas can read mousemove, document, window and body can't, idk why. + // And this will not trigger if canvas is not receiving mousemove events. + document + .getElementById("the_canvas_id") + .addEventListener("mousemove", handleMouseMove); + + // When the canvas does not receive mousemove, maybe other elements are capturing it and window should receive it. + window.addEventListener("mousemove", handleMouseMove); + + return () => { + document + .getElementById("the_canvas_id") + .removeEventListener("mousemove", handleMouseMove); + + window.removeEventListener("mousemove", handleMouseMove); + }; + }, []); + + const hoveredArea = areas + .slice() + .reverse() + .find((area) => { + return ( + area.x <= mouseX && + mouseX <= area.x + area.width && + area.y <= mouseY && + mouseY <= area.y + area.height + ); + }); + + console.log(mouseX, mouseY); + console.log(hoveredArea); return ( - <> -
- - -
-

Vite + React

-
- -

- Edit src/App.tsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- + + + + {areas.map((area) => ( + + ))} + + + + {areas + .filter((area) => area.kind === "html") + .map((area) => ( + + ))} + ); } diff --git a/companion/src/main.jsx b/companion/src/main.jsx index 2b345fc..ac138f5 100644 --- a/companion/src/main.jsx +++ b/companion/src/main.jsx @@ -2,10 +2,29 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; -export function run(root) { +export function run() { + window.hframeDebug = {}; + + const root = document.createElement("div"); + root.style.display = "contents"; + document.body.appendChild(root); + createRoot(root).render( ); } + +export function set_areas(areas) { + if (window.setAreas) { + window.hframeDebug.areas = areas; + window.setAreas(areas); + } else { + console.error("set_areas function not available"); + } +} + +export function log(message) { + console.log(message); +} diff --git a/companion/vite.config.ts b/companion/vite.config.ts index 9398e2b..308588c 100644 --- a/companion/vite.config.ts +++ b/companion/vite.config.ts @@ -18,4 +18,7 @@ export default defineConfig({ // external: ['react', 'react-dom'], }, }, + define: { + "process.env.NODE_ENV": JSON.stringify("production"), + }, }); diff --git a/src/js/companion.js b/src/js/companion.js deleted file mode 100644 index b155dec..0000000 --- a/src/js/companion.js +++ /dev/null @@ -1,156 +0,0 @@ -import { h, Component, render } from "https://esm.sh/preact@10.23.2"; -import { useState, useEffect } from "https://esm.sh/preact@10.23.2/hooks"; - -function Area({ area, interactive }) { - return h( - "foreignObject", - { - key: area.id, - x: area.x, - y: area.y, - width: area.width, - height: area.height, - style: { - overflow: "hidden", - }, - }, - [ - h("div", { - style: { - width: "100%", - height: "100%", - display: "flex", - justifyContent: "center", - alignItems: "center", - backgroundColor: "lightblue", - visibility: area.visible ? "visible" : "hidden", - pointerEvents: interactive ? "auto" : "none", - }, - onMouseEnter: () => { - console.log("Mouse entered"); - }, - dangerouslySetInnerHTML: { - __html: area.content, - }, - }), - ] - ); -} - -function MaskRect(area) { - return h("rect", { - key: area.id, - x: area.x, - y: area.y, - width: area.width, - height: area.height, - // TODO: This roundness looks good for egui windows but should not be hardcoded. - // In the future, a canvas area may not be a window. - rx: area.kind === "canvas" ? 7 : 0, - fill: area.kind === "canvas" ? "black" : "white", - }); -} - -function App() { - const [windowWidth, setWindowWidth] = useState(window.innerWidth); - const [windowHeight, setWindowHeight] = useState(window.innerHeight); - const [mouseX, setMouseX] = useState(0); - const [mouseY, setMouseY] = useState(0); - const [areas, setAreas] = useState([]); - window.setAreas = setAreas; - - useEffect(() => { - const handleResize = () => { - setWindowWidth(window.innerWidth); - setWindowHeight(window.innerHeight); - }; - - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); - - useEffect(() => { - const handleMouseMove = (event) => { - setMouseX(event.clientX); - setMouseY(event.clientY); - }; - - // Because of the svg having no pointer events, only the canvas can read mousemove, document, window and body can't, idk why. - // And this will not trigger if canvas is nor receving mousemove events. - document - .getElementById("the_canvas_id") - .addEventListener("mousemove", handleMouseMove); - - // When the canvas does not receive mousemove, maybe other elements is capturing it and window should receive it. - window.addEventListener("mousemove", handleMouseMove); - - return () => { - document - .getElementById("the_canvas_id") - .removeEventListener("mousemove", handleMouseMove); - - window.removeEventListener("mousemove", handleMouseMove); - }; - }, []); - - const hoveredArea = areas.findLast((area) => { - return ( - area.x <= mouseX && - mouseX <= area.x + area.width && - area.y <= mouseY && - mouseY <= area.y + area.height - ); - }); - console.log(mouseX, mouseY); - console.log(hoveredArea); - - return h( - "svg", - { - width: windowWidth, - height: windowHeight, - style: { - position: "absolute", - top: 0, - left: 0, - mask: "url(#mask)", - zIndex: 1000, - // Issue: This causes window mousemove events to be ignored. - pointerEvents: "none", - }, - }, - [ - h("defs", {}, [ - h( - "mask", - { - id: "mask", - }, - areas.map(MaskRect) - ), - ]), - - areas - .filter((area) => area.kind === "html") - .map((area) => Area({ area, interactive: area === hoveredArea })), - ] - ); -} - -export function run() { - window.hframeDebug = {}; - render(h(App), document.body); -} - -export function set_areas(areas) { - if (window.setAreas) { - window.hframeDebug.areas = areas; - window.setAreas(areas); - } else { - console.error("set_areas function not available"); - } -} - -export function log(message) { - console.log(message); -} diff --git a/src/web.rs b/src/web.rs index 1793523..bc104a5 100644 --- a/src/web.rs +++ b/src/web.rs @@ -5,7 +5,7 @@ mod js { use serde::{de::DeserializeOwned, Serialize}; use wasm_bindgen::prelude::*; - #[wasm_bindgen(module = "/src/js/companion.js")] + #[wasm_bindgen(module = "/companion/dist/companion.js")] extern "C" { pub(crate) fn set_areas(areas: JsValue); pub(crate) fn run();