add debug menu & flags
This commit is contained in:
parent
d262be82dd
commit
0ed579c0d7
|
@ -4,6 +4,7 @@ import { CanvasWrapper } from "./CanvasWrapper";
|
||||||
import { Pallete } from "./Pallete";
|
import { Pallete } from "./Pallete";
|
||||||
import { TemplateContext } from "../contexts/TemplateContext";
|
import { TemplateContext } from "../contexts/TemplateContext";
|
||||||
import { SettingsSidebar } from "./Settings/SettingsSidebar";
|
import { SettingsSidebar } from "./Settings/SettingsSidebar";
|
||||||
|
import { DebugModal } from "./Debug/DebugModal";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -13,6 +14,7 @@ const App = () => {
|
||||||
<CanvasWrapper />
|
<CanvasWrapper />
|
||||||
<Pallete />
|
<Pallete />
|
||||||
|
|
||||||
|
<DebugModal />
|
||||||
<SettingsSidebar />
|
<SettingsSidebar />
|
||||||
</TemplateContext>
|
</TemplateContext>
|
||||||
</AppContext>
|
</AppContext>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Debug, FlagCategory } from "@sc07-canvas/lib/src/debug";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
Switch,
|
||||||
|
useDisclosure,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
|
||||||
|
export const DebugModal = () => {
|
||||||
|
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleOpen = () => {
|
||||||
|
onOpen();
|
||||||
|
};
|
||||||
|
|
||||||
|
Debug.on("openTools", handleOpen);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
Debug.off("openTools", handleOpen);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange} placement="center">
|
||||||
|
<ModalContent>
|
||||||
|
{(onClose) => (
|
||||||
|
<>
|
||||||
|
<ModalHeader className="flex flex-col gap-1">
|
||||||
|
Debug Tools
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
<Button onPress={() => Debug.openDebug()}>
|
||||||
|
Open Debug Information
|
||||||
|
</Button>
|
||||||
|
{Debug.flags.getAll().map((flag, i, arr) => (
|
||||||
|
<>
|
||||||
|
{arr[i - 1]?.category !== flag.category && (
|
||||||
|
<p>{FlagCategory[flag.category]}</p>
|
||||||
|
)}
|
||||||
|
<div key={flag.id}>
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
defaultSelected={flag.enabled}
|
||||||
|
onValueChange={(v) => Debug.flags.setEnabled(flag.id, v)}
|
||||||
|
>
|
||||||
|
{flag.id}
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button onPress={onClose}>Close</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
import { Button } from "@nextui-org/react";
|
import { Button } from "@nextui-org/react";
|
||||||
import { useAppContext } from "../contexts/AppContext";
|
import { useAppContext } from "../contexts/AppContext";
|
||||||
import { User } from "./Header/User";
|
import { User } from "./Header/User";
|
||||||
|
import { Debug } from "@sc07-canvas/lib/src/debug";
|
||||||
|
|
||||||
export const Header = () => {
|
export const Header = () => {
|
||||||
const { setSettingsSidebar } = useAppContext();
|
const { setSettingsSidebar } = useAppContext();
|
||||||
|
@ -12,6 +13,7 @@ export const Header = () => {
|
||||||
<div className="box">
|
<div className="box">
|
||||||
<User />
|
<User />
|
||||||
<Button onClick={() => setSettingsSidebar(true)}>Settings</Button>
|
<Button onClick={() => setSettingsSidebar(true)}>Settings</Button>
|
||||||
|
<Button onClick={() => Debug.openDebugTools()}>debug</Button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
import EventEmitter from "eventemitter3";
|
||||||
|
|
||||||
|
interface DebugEvents {
|
||||||
|
openTools(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DebugArgs {
|
||||||
|
point: [x: number, y: number, id?: string];
|
||||||
|
text: [str: any];
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum FlagCategory {
|
||||||
|
"Renderer",
|
||||||
|
"DebugMessages",
|
||||||
|
"Uncategorized",
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExperimentFlag {
|
||||||
|
id: string;
|
||||||
|
enabled: boolean;
|
||||||
|
category: FlagCategory = FlagCategory.Uncategorized;
|
||||||
|
|
||||||
|
constructor(id: string, defaultEnabled = false, category?: FlagCategory) {
|
||||||
|
this.id = id;
|
||||||
|
this.enabled = defaultEnabled;
|
||||||
|
if (category) this.category = category;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FlagEvents {
|
||||||
|
enable(flag_id: string): void;
|
||||||
|
disable(flag_id: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FlagManager extends EventEmitter<FlagEvents> {
|
||||||
|
flags: ExperimentFlag[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.flags = [];
|
||||||
|
|
||||||
|
this.register(
|
||||||
|
// RENDERER
|
||||||
|
new ExperimentFlag(
|
||||||
|
"PANZOOM_PINCH_TRANSFORM_1",
|
||||||
|
false,
|
||||||
|
FlagCategory.Renderer
|
||||||
|
),
|
||||||
|
new ExperimentFlag(
|
||||||
|
"PANZOOM_PINCH_TRANSFORM_2",
|
||||||
|
false,
|
||||||
|
FlagCategory.Renderer
|
||||||
|
),
|
||||||
|
|
||||||
|
// DEBUG MESSAGES
|
||||||
|
new ExperimentFlag(
|
||||||
|
"PANZOOM_PINCH_DEBUG_MESSAGES",
|
||||||
|
false,
|
||||||
|
FlagCategory.DebugMessages
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
register(...flags: ExperimentFlag[]) {
|
||||||
|
this.flags.push(...flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFlag(flag: string) {
|
||||||
|
return this.flags.find((f) => f.id === flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled(flag: string) {
|
||||||
|
return this.getFlag(flag)?.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnabled(flagID: string, enabled: boolean) {
|
||||||
|
const flag = this.flags.find((f) => f.id === flagID);
|
||||||
|
if (!flag) throw new Error("Unknown flag " + flagID);
|
||||||
|
|
||||||
|
flag.enabled = enabled;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
this.emit("enable", flagID);
|
||||||
|
} else {
|
||||||
|
this.emit("disable", flagID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll() {
|
||||||
|
return [...this.flags].sort((a, b) => a.category - b.category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug wrapper
|
||||||
|
*
|
||||||
|
* Goals:
|
||||||
|
* - toggle debug flags (similar to Discord experiments)
|
||||||
|
* - open blank debug tab with useragent and any flags
|
||||||
|
*/
|
||||||
|
class Debugcl extends EventEmitter<DebugEvents> {
|
||||||
|
readonly flags = new FlagManager();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
openDebug() {
|
||||||
|
const wind = window.open("about:blank", "_blank");
|
||||||
|
if (!wind) {
|
||||||
|
alert(
|
||||||
|
"Failed to open debug tab. Is your anti-popup too powerful? Or did this get triggered from not a trusted event"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wind.document.write(`
|
||||||
|
<h1>debug menu</h1>
|
||||||
|
<pre>${JSON.stringify(
|
||||||
|
{
|
||||||
|
userAgent: navigator.userAgent,
|
||||||
|
flags: this.flags
|
||||||
|
.getAll()
|
||||||
|
.filter((f) => f.enabled)
|
||||||
|
.map((f) => f.id),
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}</pre>
|
||||||
|
`);
|
||||||
|
wind.document.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
openDebugTools() {
|
||||||
|
this.emit("openTools");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create debug marker
|
||||||
|
*
|
||||||
|
* Useful on touchscreen devices
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param args
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
debug<T extends keyof DebugArgs>(type: T, ...args: DebugArgs[T]) {
|
||||||
|
switch (type) {
|
||||||
|
case "point": {
|
||||||
|
const [x, y, id] = args;
|
||||||
|
|
||||||
|
if (document.getElementById("debug-" + id)) {
|
||||||
|
document.getElementById("debug-" + id)!.style.top = y + "px";
|
||||||
|
document.getElementById("debug-" + id)!.style.left = x + "px";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let el = document.createElement("div");
|
||||||
|
if (id) el.id = "debug-" + id;
|
||||||
|
el.classList.add("debug-point");
|
||||||
|
el.style.setProperty("top", y + "px");
|
||||||
|
el.style.setProperty("left", x + "px");
|
||||||
|
document.body.appendChild(el);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "text": {
|
||||||
|
const [str] = args;
|
||||||
|
|
||||||
|
// create debug box in canvas-meta if it doesn't exist
|
||||||
|
if (!document.getElementById("canvas-meta-debug")) {
|
||||||
|
let debugBox = document.createElement("div");
|
||||||
|
debugBox.id = "canvas-meta-debug";
|
||||||
|
debugBox.style.whiteSpace = "pre";
|
||||||
|
debugBox.style.unicodeBidi = "embed";
|
||||||
|
document.getElementById("canvas-meta")!.prepend(debugBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("canvas-meta-debug")!.innerText =
|
||||||
|
typeof str === "string" ? str : JSON.stringify(str, null, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Debug = new Debugcl();
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Debug } from "../../debug";
|
||||||
import { PanZoom } from "../PanZoom";
|
import { PanZoom } from "../PanZoom";
|
||||||
|
|
||||||
export function handleCalculateZoomPositions(
|
export function handleCalculateZoomPositions(
|
||||||
|
@ -17,7 +18,7 @@ export function handleCalculateZoomPositions(
|
||||||
|
|
||||||
const calculatedPositionX = x - mouseX * scaleDifference;
|
const calculatedPositionX = x - mouseX * scaleDifference;
|
||||||
const calculatedPositionY = y - mouseY * scaleDifference;
|
const calculatedPositionY = y - mouseY * scaleDifference;
|
||||||
contextInstance.debug(calculatedPositionX, calculatedPositionY, "zoom");
|
// Debug.debug("point", calculatedPositionX, calculatedPositionY, "zoom");
|
||||||
|
|
||||||
// do not limit to bounds when there is padding animation,
|
// do not limit to bounds when there is padding animation,
|
||||||
// it causes animation strange behaviour
|
// it causes animation strange behaviour
|
||||||
|
|
Loading…
Reference in New Issue