Skip to content

Commit

Permalink
Added button for hiding debug/dev tools, made debug info ignore curso…
Browse files Browse the repository at this point in the history
…r events (#484)
  • Loading branch information
rubenthoms authored Nov 29, 2023
1 parent 25a23a6 commit 15bf744
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 48 deletions.
2 changes: 2 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DrawerContent, GuiState } from "@framework/GuiMessageBroker";
import { LayoutElement, Workbench } from "@framework/Workbench";
import { NavBar } from "@framework/internal/components/NavBar";
import { SettingsContentPanels } from "@framework/internal/components/SettingsContentPanels";
import { ToggleDevToolsButton } from "@framework/internal/components/ToggleDevToolsButton";
import { AuthState, useAuthProvider } from "@framework/internal/providers/AuthProvider";
import { Button } from "@lib/components/Button";
import { WebvizSpinner } from "@lib/components/WebvizSpinner";
Expand Down Expand Up @@ -136,6 +137,7 @@ function App() {
<NavBar workbench={workbench.current} />
<SettingsContentPanels workbench={workbench.current} />
</div>
<ToggleDevToolsButton guiMessageBroker={workbench.current.getGuiMessageBroker()} />
</>
);
}
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/framework/GuiMessageBroker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";

import { isDevMode } from "@lib/utils/devMode";
import { Point } from "@lib/utils/geometry";

import { GlobalCursor } from "./internal/GlobalCursor";
Expand All @@ -17,6 +18,7 @@ export enum GuiState {
SettingsPanelWidthInPercent = "settingsPanelWidthInPercent",
ActiveModuleInstanceId = "activeModuleInstanceId",
DataChannelConnectionLayerVisible = "dataChannelConnectionLayerVisible",
DevToolsVisible = "devToolsVisible",
}

export enum GuiEvent {
Expand Down Expand Up @@ -70,14 +72,17 @@ type GuiStateValueTypes = {
[GuiState.SettingsPanelWidthInPercent]: number;
[GuiState.ActiveModuleInstanceId]: string;
[GuiState.DataChannelConnectionLayerVisible]: boolean;
[GuiState.DevToolsVisible]: boolean;
};

const defaultStates: Map<GuiState, any> = new Map();
defaultStates.set(GuiState.DrawerContent, DrawerContent.ModuleSettings);
defaultStates.set(GuiState.SettingsPanelWidthInPercent, 30);
defaultStates.set(GuiState.ActiveModuleInstanceId, "");
defaultStates.set(GuiState.DataChannelConnectionLayerVisible, false);
defaultStates.set(GuiState.DevToolsVisible, isDevMode());

const persistentStates: GuiState[] = [GuiState.SettingsPanelWidthInPercent];
const persistentStates: GuiState[] = [GuiState.SettingsPanelWidthInPercent, GuiState.DevToolsVisible];

export class GuiMessageBroker {
private _eventListeners: Map<GuiEvent, Set<(event: any) => void>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export const ViewContent = React.memo((props: ViewContentProps) => {
id={`${props.moduleInstance.getId()}-view`}
statusController={props.moduleInstance.getStatusController()}
source={StatusSource.View}
guiMessageBroker={props.workbench.getGuiMessageBroker()}
>
<View
moduleContext={props.moduleInstance.getContext()}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";

import { GuiMessageBroker, GuiState, useGuiValue } from "@framework/GuiMessageBroker";
import { StatusSource } from "@framework/ModuleInstanceStatusController";
import {
ModuleInstanceStatusControllerInternal,
Expand Down Expand Up @@ -43,6 +44,7 @@ export type DebugProfilerProps = {
children: React.ReactNode;
statusController: ModuleInstanceStatusControllerInternal;
source: StatusSource;
guiMessageBroker: GuiMessageBroker;
};

type RenderInfo = {
Expand All @@ -69,6 +71,7 @@ export const DebugProfiler: React.FC<DebugProfilerProps> = (props) => {
props.statusController,
props.source === StatusSource.View ? "viewDebugMessage" : "settingsDebugMessage"
);
const debugInfoVisible = useGuiValue(props.guiMessageBroker, GuiState.DevToolsVisible);

const handleRender = React.useCallback(
(
Expand Down Expand Up @@ -103,55 +106,57 @@ export const DebugProfiler: React.FC<DebugProfilerProps> = (props) => {
<DebugProfilerWrapper id={props.id} onRender={handleRender}>
{props.children}
</DebugProfilerWrapper>
<div className="absolute bottom-1 w-full flex gap-2 flex-wrap">
{renderInfo && (
<>
{reportedRenderCount !== null && (
<DebugProfilerRenderInfo title="Reported component render count">
Component RC: {reportedRenderCount}
{debugInfoVisible && (
<div className="absolute bottom-1 w-full flex gap-2 flex-wrap pointer-events-none">
{renderInfo && (
<>
{reportedRenderCount !== null && (
<DebugProfilerRenderInfo title="Reported component render count">
Component RC: {reportedRenderCount}
</DebugProfilerRenderInfo>
)}
{customDebugMessage && (
<DebugProfilerRenderInfo title="Custom debug message">
Message: {customDebugMessage}
</DebugProfilerRenderInfo>
)}
<DebugProfilerRenderInfo title="Tree render count">
Tree RC: {renderInfo.renderCount}
</DebugProfilerRenderInfo>
)}
{customDebugMessage && (
<DebugProfilerRenderInfo title="Custom debug message">
Message: {customDebugMessage}
<DebugProfilerRenderInfo title="Phase">P: {renderInfo.phase}</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo
title={
"Actual duration: The number of milliseconds spent rendering the module and its descendants for the current update. " +
"This indicates how well the subtree makes use of memoization (e.g. memo and useMemo). " +
"Ideally this value should decrease significantly after the initial mount as many of the descendants will only " +
"need to re-render if their specific props change."
}
>
AD: {renderInfo.actualDuration.toFixed(2)}ms
</DebugProfilerRenderInfo>
)}
<DebugProfilerRenderInfo title="Tree render count">
Tree RC: {renderInfo.renderCount}
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="Phase">P: {renderInfo.phase}</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo
title={
"Actual duration: The number of milliseconds spent rendering the module and its descendants for the current update. " +
"This indicates how well the subtree makes use of memoization (e.g. memo and useMemo). " +
"Ideally this value should decrease significantly after the initial mount as many of the descendants will only " +
"need to re-render if their specific props change."
}
>
AD: {renderInfo.actualDuration.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo
title={
"Base Duration: The number of milliseconds estimating how much time it would take to re-render the entire module subtree without any optimizations. " +
"It is calculated by summing up the most recent render durations of each component in the tree. " +
"This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization). " +
"Compare actualDuration against it to see if memoization is working."
}
>
BD: {renderInfo.baseDuration.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the fastest render duration.">
MIN: {renderInfo.minTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the slowest render duration.">
MAX: {renderInfo.maxTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the average render duration.">
AVG: {renderInfo.avgTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
</>
)}
</div>
<DebugProfilerRenderInfo
title={
"Base Duration: The number of milliseconds estimating how much time it would take to re-render the entire module subtree without any optimizations. " +
"It is calculated by summing up the most recent render durations of each component in the tree. " +
"This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization). " +
"Compare actualDuration against it to see if memoization is working."
}
>
BD: {renderInfo.baseDuration.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the fastest render duration.">
MIN: {renderInfo.minTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the slowest render duration.">
MAX: {renderInfo.maxTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
<DebugProfilerRenderInfo title="The number of milliseconds of the average render duration.">
AVG: {renderInfo.avgTime.toFixed(2)}ms
</DebugProfilerRenderInfo>
</>
)}
</div>
)}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const Setting: React.FC<SettingProps> = (props) => {
id={`${props.moduleInstance.getId()}-settings`}
source={StatusSource.Settings}
statusController={props.moduleInstance.getStatusController()}
guiMessageBroker={props.workbench.getGuiMessageBroker()}
>
<Settings
moduleContext={props.moduleInstance.getContext()}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { ToggleDevToolsButton } from "./toggleDevToolsButton";
export type { ToggleDevToolsButtonProps } from "./toggleDevToolsButton";
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";

import { GuiMessageBroker, GuiState, useGuiState } from "@framework/GuiMessageBroker";
import { isDevMode } from "@lib/utils/devMode";
import { resolveClassNames } from "@lib/utils/resolveClassNames";
import { BugReport } from "@mui/icons-material";

export type ToggleDevToolsButtonProps = {
guiMessageBroker: GuiMessageBroker;
};

export const ToggleDevToolsButton: React.FC<ToggleDevToolsButtonProps> = (props) => {
const [devToolsVisible, setDevToolsVisible] = useGuiState(props.guiMessageBroker, GuiState.DevToolsVisible);

React.useEffect(() => {
if (!devToolsVisible) {
document.querySelector(".tsqd-parent-container")?.classList.add("hidden");
} else {
document.querySelector(".tsqd-parent-container")?.classList.remove("hidden");
}
}, [devToolsVisible]);

if (!isDevMode()) {
return null;
}

return (
<div
className={resolveClassNames(
"absolute bottom-2 shadow left-3 z-50 m-2 p-2 rounded-full flex items-center justify-center w-8 h-8 bg-gray-800 text-white text-m cursor-pointer",
{
"bg-green-700 hover: hover:bg-green-600": devToolsVisible,
"bg-gray-800 hover:bg-gray-700": !devToolsVisible,
}
)}
title={devToolsVisible ? "Hide dev tools" : "Show dev tools"}
onClick={() => {
setDevToolsVisible(!devToolsVisible);
}}
>
<BugReport fontSize="inherit" />
</div>
);
};

0 comments on commit 15bf744

Please sign in to comment.